package com.sf.fy.uav.order.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sf.fy.uav.common.awt.JwtUtil;
import com.sf.fy.uav.common.enums.*;
import com.sf.fy.uav.common.exception.BusinessException;
import com.sf.fy.uav.common.request.common.IdRequest;
import com.sf.fy.uav.common.request.operate.OrderInfoReq;
import com.sf.fy.uav.common.request.order.*;
import com.sf.fy.uav.common.response.operational.CommodityQuery;
import com.sf.fy.uav.common.response.operational.OrderInfoRes;
import com.sf.fy.uav.common.response.order.*;
import com.sf.fy.uav.common.response.order.task.DistributionOrderListRes;
import com.sf.fy.uav.common.response.order.task.ScenicSpotOrderDetailRes;
import com.sf.fy.uav.common.utils.*;
import com.sf.fy.uav.controller.*;
import com.sf.fy.uav.entity.*;
import com.sf.fy.uav.good.entity.CityGoodsType;
import com.sf.fy.uav.good.entity.TaskGoods;
import com.sf.fy.uav.good.mapper.CityGoodsTypeMapper;
import com.sf.fy.uav.good.mapper.GoodsTypeMapper;
import com.sf.fy.uav.good.mapper.TaskGoodsMapper;
import com.sf.fy.uav.mapper.*;
import com.sf.fy.uav.order.controller.BillRest;
import com.sf.fy.uav.order.controller.CityAirportRest;
import com.sf.fy.uav.order.controller.PricingRest;
import com.sf.fy.uav.order.entity.*;
import com.sf.fy.uav.order.mapper.BillMapper;
import com.sf.fy.uav.order.mapper.ExpenseDetailsMapper;
import com.sf.fy.uav.order.mapper.OrderInfoMapper;
import com.sf.fy.uav.order.service.IOrderInfoService;
import com.sf.fy.uav.order.service.LoginOrderService;
import com.sf.fy.uav.order.util.BatchDecryptionUtil;
import com.sf.fy.uav.rest.*;
import com.sf.fy.uav.rest.entity.TtTesTerminal;
import com.sf.fy.uav.rest.mapper.TtTesTerminalMapper;
import com.sf.fy.uav.service.IErrandOrderService;
import com.sf.fy.uav.service.IProductTypeService;
import com.sf.fy.uav.sms.rest.WxAppletRest;
import com.sf.fy.uav.task.controller.TaskStatusLogRest;
import com.sf.fy.uav.task.entity.TaskStatusLog;
import com.sf.fy.uav.task.mapper.TaskStatusLogMapper;
import com.sf.fy.uav.task.rest.IntraCityRest;
import com.sf.fy.uav.user.controller.UserCompanyRest;
import com.sf.fy.uav.user.controller.UserWalletRest;
import com.sf.fy.uav.user.entity.RewardBill;
import com.sf.fy.uav.user.entity.User;
import com.sf.fy.uav.user.entity.UserCompany;
import com.sf.fy.uav.user.entity.UserWallet;
import com.sf.fy.uav.user.mapper.RewardBillMapper;
import com.sf.fy.uav.user.mapper.UserCompanyMapper;
import com.sf.fy.uav.user.mapper.UserMapper;
import com.sf.fy.uav.user.mapper.UserWalletMapper;
import com.sf.fy.uav.utils.AirportInfoUtils;
import com.sf.fy.uav.withdrawal.entity.ScenicSpot;
import com.sf.fy.uav.withdrawal.mapper.ScenicSpotMapper;
import com.sfpay.sdk.OpenClient;
import com.sfpay.sdk.entity.callback.TradeRefundCallback;
import com.sfpay.sdk.entity.request.trade.TradeRefundApplyRequest;
import com.sfpay.sdk.entity.request.trade.TradeRefundApplyResponse;
import com.sfpay.sdk.entity.request.trade.TradeRefundQueryRequest;
import com.sfpay.sdk.entity.request.trade.TradeRefundQueryResponse;
import io.seata.core.context.RootContext;
import io.swagger.annotations.ApiModelProperty;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.RequestParam;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author LTQ
 * @since 2023-05-08
 */
@Service
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements IOrderInfoService {
    private final static Logger logger = LoggerFactory.getLogger(OrderInfoServiceImpl.class);

    @Autowired
    private OrderInfoMapper orderInfoMapper;

    @Autowired
    private ErrandOrderController errandOrderController;


    @Autowired
    private IErrandOrderService iErrandOrderService;

    @Autowired
    private PhoneEncoderUtil phoneEncoderUtil;

    @Autowired
    private ErrandOrderMapper errandOrderMapper;

    @Autowired
    private UserCouponRest userCouponRest;

    @Autowired
    private UserCompanyRest userCompanyRest;

    @Autowired
    private UserCompanyMapper userCompanyMapper;

    @Autowired
    private CityAirportRest cityAirportRest;

    @Autowired
    private ExpenseDetailsMapper expenseDetailsMapper;

    @Autowired
    private TtTesTerminalMapper ttTesTerminalMapper;

    @Autowired
    private PricingRest pricingRest;

    @Autowired
    private SpecialPricingRest specialPricingRest;


    @Value("${express.fee:20}")
    private BigDecimal expressFee;

    @Value("${delivery_time.same_city:2}")
    private double sameCityDeliveryTime;

    @Value("${delivery_time.cross_city:3}")
    private double crossCityDeliveryTime;

    @Value("${max_weight.same_city:10}")
    private double sameCityMaxWeight;

    @Value("${max_weight.cross_city:15}")
    private double crossCityMaxWeight;

    @Autowired
    private PromotionStatisticsRest promotionStatisticsRest;

    @Autowired
    private UserWalletRest userWalletRest;

    @Autowired
    private PromotionRecordsMapper promotionRecordsMapper;


    @Autowired
    private IntraCityRest intraCityRest;

    @Autowired
    private AirportInfoUtils airportInfoController;

    @Autowired
    private TaskStatusLogMapper taskStatusLogMapper;


    @Autowired
    private TaskGoodsMapper taskGoodsMapper;

    @Autowired
    private BatchDecryptionUtils batchDecryptionUtils;

    @Autowired
    private GoodsTypeMapper goodsTypeMapper;

    @Autowired
    private CityGoodsTypeMapper cityGoodsTypeMapper;

    @Autowired
    private TaskStatusLogRest taskStatusLogRest;

    @Autowired
    private UserCouponMapper userCouponMapper;

    @Autowired
    private CouponMapper couponMapper;

    @Autowired
    private BillMapper billMapper;

    @Autowired
    private PlacementPointRest placementPointRest;
    @Autowired
    private BusinessRest businessRest;
    @Autowired
    private ScenicSpotRest scenicSpotRest;
    @Autowired
    private CommodityRest commodityRest;

    @Autowired
    private ActivityRest activityRest;

    @Autowired
    private InvitationCodeMapper invitationCodeMapper;

    @Autowired
    private InvitationRecordMapper invitationRecordMapper;
    @Autowired
    private OrderCommodityRest orderCommodityRest;
    @Autowired
    private LoginOrderService loginService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private BillRest billRest;
    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private SysTcRest sysTcRest;

    @Autowired
    private PromotionStatisticsMapper promotionStatisticsMapper;

    @Autowired
    private UserWalletMapper userWalletMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RewardBillMapper rewardBillMapper;

    @Autowired
    private IProductTypeService iProductTypeService;

    @Value("${pay.refund-confirm-url:http://127.0.0.1:8080/trade/callback}")
    private String refundConfirmUrl;


    @Value("${callback.url:https://ie-uocs-out.sit.sf-express.com:4433/uocs-intracity/}")
    private String callbackUrl;
    @Value("${lock.try_time:3}")
    private long lockTryTime;

    @Value("${wx.update-status-template-id:qx_RfGPurM78ZlG4Qqa4RzIXZxlSAgo5mIIJsslmb6U}")
    private String updateStatusTemplateId;

    @Value("${wx.update-status-template-id:DyZzQXtOw2iXdd63ZETf-40AVO_q8Ip305yplDfs2qc}")
    private String updateExpressStatusTemplateId;

    @Value("${wx.delivery-start-template-id:Qy_sG7jpaXYE_GApiS21Ozj4m7L8dZo334Es-dKtbRU}")
    private String deliveryStartTemplateId;

    @Value("${wx.delivery-completed-template-id:iyP1qBbENLnK1yx3ChKN72rRu1Y4WxKmtrHH1WkWhCU}")
    private String deliveryCompletedTemplateId;

    @Autowired
    private PlacementPointMapper placementPointMapper;

    @Autowired
    private ScenicSpotMapper scenicSpotMapper;

    @Autowired
    private CommodityMapper commodityMapper;

    @Autowired
    private WxAppletRest wxAppletRest;

    @Autowired
    private BatchDecryptionUtil batchDecryptionUtil;

    private final static Integer PLATFORM_CODE = 1;

    private final static Integer MONTHLY_STATEMENT_PLATFORM_CODE = 4;

    SimpleDateFormat sdf = new SimpleDateFormat("YYYY年MM月dd日 HH:mm:ss");

    @Override
    public void add(OrderInfoAddRequest orderInfoAddRequest) {
        OrderInfo orderInfo = BeanUtil.copyProperties(orderInfoAddRequest, OrderInfo.class);
        this.insert(orderInfo);
    }

    @Override
    public List<OrderResponse> getSendOrder(Integer page, Integer size) {
        String userId = JwtUtil.getUserId();
        QueryWrapper<OrderInfo> orderInfoQueryWrapper = new QueryWrapper<>();
        Page<OrderInfo> orderInfoPage = new Page<>(page, size);
        orderInfoQueryWrapper.eq("user_id", userId);
        orderInfoQueryWrapper.orderByDesc("create_time");
        IPage<OrderInfo> orderInfoIPage = this.selectPage(orderInfoPage, orderInfoQueryWrapper);
        List<OrderResponse> orderResponses = this.dto(orderInfoIPage.getRecords());
        return orderResponses;
    }

    @Override
    public List<OrderInfo> getOrders(Integer page, Integer size) {
        String userId = JwtUtil.getUserId();
        QueryWrapper<OrderInfo> orderInfoQueryWrapper = new QueryWrapper<>();
        Page<OrderInfo> orderInfoPage = new Page<>(page, size);
        orderInfoQueryWrapper.eq("user_id", userId);
        orderInfoQueryWrapper.orderByDesc("create_time");
        IPage<OrderInfo> orderInfoIPage = this.selectPage(orderInfoPage, orderInfoQueryWrapper);
        return orderInfoIPage.getRecords();
    }

    @Override
    public Long getSendOrderTotal() {
        String userId = JwtUtil.getUserId();
        QueryWrapper<OrderInfo> orderInfoQueryWrapper = new QueryWrapper<>();
        orderInfoQueryWrapper.eq("user_id", userId);
        return orderInfoMapper.selectCount(orderInfoQueryWrapper);
    }

    @Override
    public Long getReceiveOrderTotal(String phone) {
        QueryWrapper<OrderInfo> orderInfoQueryWrapper = new QueryWrapper<>();
        phone = phoneEncoderUtil.encryptString(phone);
        String finalPhone = phone;
        orderInfoQueryWrapper.and(wrapper -> wrapper.eq("receiver_tel", finalPhone));
        ArrayList arrayList = new ArrayList();
        arrayList.add(PlatformCodeEnum.FY_EXPRESS.getCode());
        arrayList.add(PlatformCodeEnum.MONTHLY_SETTLEMENT_PLATFORM.getCode());
        orderInfoQueryWrapper.in("platform_code", arrayList);
        return orderInfoMapper.selectCount(orderInfoQueryWrapper);
    }

    @Override
    public List<OrderResponse> getReceiveOrder(String phone, Integer page, Integer size) {
        QueryWrapper<OrderInfo> orderInfoQueryWrapper = new QueryWrapper<>();
        Page<OrderInfo> orderInfoPage = new Page<>(page, size);
        phone = phoneEncoderUtil.encryptString(phone);
        String finalPhone = phone;
        orderInfoQueryWrapper.and(wrapper -> wrapper.eq("receiver_tel", finalPhone));
        ArrayList arrayList = new ArrayList();
        arrayList.add(PlatformCodeEnum.FY_EXPRESS.getCode());
        arrayList.add(PlatformCodeEnum.MONTHLY_SETTLEMENT_PLATFORM.getCode());
        orderInfoQueryWrapper.in("platform_code", arrayList);
        orderInfoQueryWrapper.orderByDesc("create_time");
        IPage<OrderInfo> orderInfoIPage = this.selectPage(orderInfoPage, orderInfoQueryWrapper);
        List<OrderResponse> taskResponses = this.dto(orderInfoIPage.getRecords());
        return taskResponses;
    }

    @Override
    public Long getTotal(@RequestParam(required = false) String tcWaybillNo, @RequestParam(required = false) String tradeNo, @RequestParam(required = false) Integer type, @RequestParam(required = false) Integer platformCode, String enterpriseId, Integer payStatus, Date startTransactionTime, Date endTransactionTime) {
        List<OrderInfo> orderInfoList;
        QueryWrapper<OrderInfo> orderInfoQueryWrapper = new QueryWrapper<>();
        List<String> ids;
        QueryWrapper<Bill> billQueryWrapper = new QueryWrapper<>();
        String userId = getUserId(enterpriseId);
        if (StringUtils.isNotBlank(tcWaybillNo) || StringUtils.isNotBlank(tradeNo) || platformCode != null) {
            if (!ObjectUtils.isEmpty(tcWaybillNo)) {
                orderInfoQueryWrapper.like("tc_waybill_no", tcWaybillNo);
            }
            if (!ObjectUtils.isEmpty(tradeNo)) {
                orderInfoQueryWrapper.like("trade_no", tradeNo);
            }
            if (!ObjectUtils.isEmpty(platformCode)) {
                orderInfoQueryWrapper.eq("platform_code", platformCode);
            }
            orderInfoList = this.selectList(orderInfoQueryWrapper);
            if (CollectionUtils.isEmpty(orderInfoList)) {
                return 0L;
            }
            ids = orderInfoList.stream().map(orderInfo -> orderInfo.getId()).collect(Collectors.toList());
            billQueryWrapper.in("order_id", ids);
        }
        if (!ObjectUtils.isEmpty(type)) {
            billQueryWrapper.eq("type", type);
        }
        if (!ObjectUtils.isEmpty(startTransactionTime)) {
            billQueryWrapper.ge("create_time", startTransactionTime);
        }
        if (!ObjectUtils.isEmpty(payStatus)) {
            billQueryWrapper.eq("pay_status", payStatus);
        }
        if (!ObjectUtils.isEmpty(userId)) {
            billQueryWrapper.eq("user_id", userId);
        }
        if (!ObjectUtils.isEmpty(endTransactionTime)) {
            billQueryWrapper.le("create_time", endTransactionTime);
        }
        Long cnt = billMapper.selectCount(billQueryWrapper);

        return cnt;
    }

    @Override
    public List<BillingResponse> getBillings(Integer page, Integer size, String tcWaybillNo, String tradeNo, Integer type, Integer platformCode, String enterpriseId, Integer payStatus, Date startTransactionTime, Date endTransactionTime) {
        List<OrderInfo> orderInfoList = new ArrayList<>();
        QueryWrapper<OrderInfo> orderInfoQueryWrapper = new QueryWrapper<>();
        String userId = getUserId(enterpriseId);
        List<String> ids;
        QueryWrapper<Bill> billQueryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(tcWaybillNo) || StringUtils.isNotBlank(tradeNo) || platformCode != null) {
            if (!ObjectUtils.isEmpty(tcWaybillNo)) {
                orderInfoQueryWrapper.like("tc_waybill_no", tcWaybillNo);
            }
            if (!ObjectUtils.isEmpty(tradeNo)) {
                orderInfoQueryWrapper.like("trade_no", tradeNo);
            }
            if (!ObjectUtils.isEmpty(platformCode)) {
                orderInfoQueryWrapper.eq("platform_code", platformCode);
            }
            orderInfoList = this.selectList(orderInfoQueryWrapper);
            if (CollectionUtils.isEmpty(orderInfoList)) {
                return new ArrayList<>();
            }
            ids = orderInfoList.stream().map(orderInfo -> orderInfo.getId()).collect(Collectors.toList());
            billQueryWrapper.in("order_id", ids);
        }

        if (!ObjectUtils.isEmpty(startTransactionTime)) {
            billQueryWrapper.ge("create_time", startTransactionTime);
        }
        if (!ObjectUtils.isEmpty(payStatus)) {
            billQueryWrapper.eq("pay_status", payStatus);
        }
        if (!ObjectUtils.isEmpty(userId)) {
            billQueryWrapper.eq("user_id", userId);
        }
        if (!ObjectUtils.isEmpty(endTransactionTime)) {
            billQueryWrapper.le("create_time", endTransactionTime);
        }

        if (!ObjectUtils.isEmpty(type)) {
            billQueryWrapper.eq("type", type);
        }
        billQueryWrapper.orderByDesc("create_time");
        List<Bill> bills;
        if (ObjectUtils.isEmpty(page) && ObjectUtils.isEmpty(size)) {
            bills = billMapper.selectList(billQueryWrapper);
        } else {
            Page<Bill> billPage = new Page<>(page, size);
            IPage<Bill> billiPage = billMapper.selectPage(billPage, billQueryWrapper);
            bills = billiPage.getRecords();
        }
        Map<String, String> userIdAndPhoneMap;
        Map<String, UserCompany> userIdAndUserCompanyMap;
        if (!CollectionUtils.isEmpty(bills)) {
            ids = bills.stream().map(Bill::getOrderId).collect(Collectors.toList());
            Set<String> userIds = bills.stream().map(Bill::getUserId).collect(Collectors.toSet());
            List<UserCompany> userCompanyList = userCompanyMapper.selectList(new QueryWrapper<UserCompany>().in("user_id", userIds));
            userIdAndUserCompanyMap = userCompanyList.stream().collect(Collectors.toMap(UserCompany::getUserId, each -> each, (value1, value2) -> value1));
            List<User> users = userMapper.selectBatchIds(userIds);
            userIdAndPhoneMap = users.stream().collect(Collectors.toMap(User::getId, User::getPhoneNumber, (value1, value2) -> value1));
            orderInfoQueryWrapper = new QueryWrapper<>();
            orderInfoQueryWrapper.in("id", ids);
            orderInfoList = this.selectList(orderInfoQueryWrapper);
        } else {
            userIdAndPhoneMap = new HashMap<>(10);
            userIdAndUserCompanyMap = new HashMap<>(10);
        }
        List<BillingResponse> billingResponses = new ArrayList<>();
        List<OrderInfo> finalOrderInfoList = orderInfoList;
        bills.forEach(bill -> {
            BillingResponse billingResponse = new BillingResponse();
            billingResponse.setId(bill.getId());
            billingResponse.setUpdateTime(bill.getUpdateTime());
            billingResponse.setCreateTime(bill.getCreateTime());
            billingResponse.setPayStatus(bill.getPayStatus());
            billingResponse.setType(bill.getType());
            billingResponse.setUserId(bill.getUserId());
            billingResponse.setRefundFailedReason(bill.getRefundFailedReason());
            finalOrderInfoList.forEach(orderInfo -> {
                if (bill.getOrderId().equals(orderInfo.getId())) {
                    billingResponse.setPricePaid(orderInfo.getPricePaid());
                    billingResponse.setPayChannel(orderInfo.getPayChannel());
                    billingResponse.setSettleChannel(orderInfo.getSettleChannel());
                    billingResponse.setPlatformCode(orderInfo.getPlatformCode());
                    if (MONTHLY_STATEMENT_PLATFORM_CODE.equals(orderInfo.getPlatformCode()) && !ObjectUtils.isEmpty(userIdAndUserCompanyMap.get(bill.getUserId()))) {
                        billingResponse.setUserName(userIdAndUserCompanyMap.get(bill.getUserId()).getEnterpriseId());
                        billingResponse.setEnterpriseName(userIdAndUserCompanyMap.get(bill.getUserId()).getCompanyName());
                    } else {
                        billingResponse.setUserName(DesensitizedUtil.desensitized(phoneEncoderUtil.decryptString(userIdAndPhoneMap.get(bill.getUserId())), DesensitizedUtil.DesensitizedType.MOBILE_PHONE));
                    }
                    billingResponse.setRemark(orderInfo.getRemark());
                    billingResponse.setTradeNo(orderInfo.getTradeNo());
                    billingResponse.setTcWaybillNo(orderInfo.getTcWaybillNo());
                    billingResponse.setChannelPayNo(orderInfo.getChannelPayNo());
                    billingResponse.setSfpayPayNo(orderInfo.getSfpayPayNo());
                }
            });
            billingResponses.add(billingResponse);
        });
        return billingResponses;
    }

    private String getUserId(String enterpriseId) {
        UserCompany userCompany = null;
        String userId = null;
        if (StringUtils.isNotBlank(enterpriseId)) {
            userCompany = userCompanyMapper.selectOne(new QueryWrapper<UserCompany>().eq("enterprise_id", enterpriseId));
        }
        if (!ObjectUtils.isEmpty(userCompany)) {
            userId = userCompany.getUserId();
        }
        return userId;
    }

    @Override
    public int insert(OrderInfo entity) {
        String senderDoorplate = entity.getSenderDoorplate();
        String receiverDoorplate = entity.getReceiverDoorplate();
        String senderTel = entity.getSenderTel();
        String receiverTel = entity.getReceiverTel();
        if (!ObjectUtils.isEmpty(senderDoorplate)) {
            senderDoorplate = phoneEncoderUtil.encryptString(senderDoorplate);
            entity.setSenderDoorplate(senderDoorplate);
        }
        if (!ObjectUtils.isEmpty(receiverDoorplate)) {
            receiverDoorplate = phoneEncoderUtil.encryptString(receiverDoorplate);
            entity.setReceiverDoorplate(receiverDoorplate);
        }
        if (!ObjectUtils.isEmpty(senderTel)) {
            senderTel = phoneEncoderUtil.encryptString(senderTel);
            entity.setSenderTel(senderTel);
        }
        if (!ObjectUtils.isEmpty(receiverTel)) {
            receiverTel = phoneEncoderUtil.encryptString(receiverTel);
            entity.setReceiverTel(receiverTel);
        }
        return orderInfoMapper.insert(entity);
    }

    @Override
    public List<OrderInfo> selectList(Wrapper<OrderInfo> queryWrapper) {
        List<OrderInfo> orderInfoList = orderInfoMapper.selectList(queryWrapper);
        orderInfoList.forEach(orderInfo -> {
            String senderDoorplate = orderInfo.getSenderDoorplate();
            String receiverDoorplate = orderInfo.getReceiverDoorplate();
            senderDoorplate = phoneEncoderUtil.decryptString(senderDoorplate);
            receiverDoorplate = phoneEncoderUtil.decryptString(receiverDoorplate);
            orderInfo.setSenderDoorplate(senderDoorplate);
            orderInfo.setReceiverDoorplate(receiverDoorplate);
        });
        return orderInfoMapper.selectList(queryWrapper);
    }

    @Override
    public IPage<OrderInfo> selectPage(Page page, Wrapper<OrderInfo> queryWrapper) {
        IPage<OrderInfo> orderInfoIPage = orderInfoMapper.selectPage(page, queryWrapper);
        List<OrderInfo> orderInfoList = orderInfoIPage.getRecords();
        orderInfoList.forEach(orderInfo -> {
            String senderTel = orderInfo.getSenderTel();
            String receiverTel = orderInfo.getReceiverTel();

            String receiverDoorplate = orderInfo.getReceiverDoorplate();

            String senderDoorplate = orderInfo.getSenderDoorplate();
            senderTel = phoneEncoderUtil.decryptString(senderTel);
            receiverTel = phoneEncoderUtil.decryptString(receiverTel);
            receiverDoorplate = phoneEncoderUtil.decryptString(receiverDoorplate);
            senderDoorplate = phoneEncoderUtil.decryptString(senderDoorplate);
            orderInfo.setSenderTel(senderTel);
            orderInfo.setReceiverTel(receiverTel);
            orderInfo.setReceiverDoorplate(receiverDoorplate);
            orderInfo.setSenderDoorplate(senderDoorplate);
        });
        return orderInfoIPage;
    }

    @Override
    public OrderInfo selectOne(Wrapper<OrderInfo> queryWrapper) {
        OrderInfo orderInfo = orderInfoMapper.selectOne(queryWrapper);
        String senderTel = orderInfo.getSenderTel();
        String receiverTel = orderInfo.getReceiverTel();

        String senderDoorplate = orderInfo.getSenderDoorplate();
        String receiverDoorplate = orderInfo.getReceiverDoorplate();
        senderTel = phoneEncoderUtil.decryptString(senderTel);
        receiverTel = phoneEncoderUtil.decryptString(receiverTel);

        senderDoorplate = phoneEncoderUtil.decryptString(senderDoorplate);
        receiverDoorplate = phoneEncoderUtil.decryptString(receiverDoorplate);
        orderInfo.setSenderTel(senderTel);
        orderInfo.setReceiverTel(receiverTel);

        orderInfo.setSenderDoorplate(senderDoorplate);
        orderInfo.setReceiverDoorplate(receiverDoorplate);
        return orderInfo;
    }

    @Override
    public RespJsonPageData<OrderInfoRes> getScenicSpotOrder(OrderInfoReq orderInfoReq) {
        List<PlacementPoint> placementPointList = new ArrayList<>();
        if (StringUtils.isNotBlank(orderInfoReq.getScenicSpotId())) {
            placementPointList = placementPointRest.getPlacementPointList(orderInfoReq.getScenicSpotId());
        }
        Set<String> placementPointIds = null;
        if (!CollectionUtils.isEmpty(placementPointList)) {
            placementPointIds = placementPointList.stream().map(PlacementPoint::getId).collect(Collectors.toSet());
        }
        List<String> scenicSpotIds;
        List<PlacementPoint> placementPoints;
        Set<String> placementPointIdsTwo = null;

        if (StringUtils.isNotBlank(orderInfoReq.getBusinessId())) {
            List<Business> businessesList = businessRest.getBusinessesByBusinessId(orderInfoReq.getBusinessId());
            if (!CollectionUtils.isEmpty(businessesList)) {
                scenicSpotIds = businessesList.stream().map(Business::getScenicSpotId).toList();
                placementPoints = placementPointRest.getPlacementPointListByScenicSpotIds(scenicSpotIds);
                placementPointIdsTwo = placementPoints.stream().map(PlacementPoint::getId).collect(Collectors.toSet());
            }
        }
        List<OrderInfoRes> orderInfoResList = new ArrayList<>();
        Set<String> placementPointIdsThree = null;
        if (!CollectionUtils.isEmpty(placementPointIds) && !CollectionUtils.isEmpty(placementPointIdsTwo)) {
            placementPointIdsThree = intersectionForList3(placementPointIds, placementPointIds);
        }
        if (!CollectionUtils.isEmpty(placementPointIdsThree)) {
            List<PlacementPoint> placementPointListTwo = placementPointRest.getPlacementPointListByIds(placementPointIdsThree);
            if (CollectionUtils.isEmpty(placementPointListTwo)) {
                return RespJsonPageData.success(orderInfoResList, 0);
            } else {
                Set<String> scenicSpotIdLists = placementPointListTwo.stream().map(PlacementPoint::getScenicSpotId).collect(Collectors.toSet());
                if (CollectionUtils.isEmpty(scenicSpotIdLists)) {
                    return RespJsonPageData.success(orderInfoResList, 0);
                } else {
                    List<ScenicSpot> scenicSpotList = scenicSpotRest.selectScenicSpotListByIds(scenicSpotIdLists);
                    if (CollectionUtils.isEmpty(scenicSpotList)) {
                        return RespJsonPageData.success(orderInfoResList, 0);
                    }
                }
            }
        }
        LambdaQueryWrapper<OrderInfo> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(StringUtils.isNotBlank(orderInfoReq.getTcWayBillNo()), OrderInfo::getTcWaybillNo, orderInfoReq.getTcWayBillNo()).in(StringUtils.isNotBlank(orderInfoReq.getScenicSpotId()) && StringUtils.isBlank(orderInfoReq.getBusinessId()) && !CollectionUtils.isEmpty(placementPointIds), OrderInfo::getPlacementPointId, placementPointIds).in(StringUtils.isNotBlank(orderInfoReq.getBusinessId()) && StringUtils.isBlank(orderInfoReq.getScenicSpotId()) && !CollectionUtils.isEmpty(placementPointIdsTwo), OrderInfo::getPlacementPointId, placementPointIdsTwo).in(StringUtils.isNotBlank(orderInfoReq.getBusinessId()) && StringUtils.isNotBlank(orderInfoReq.getScenicSpotId()) && !CollectionUtils.isEmpty(placementPointIdsThree), OrderInfo::getPlacementPointId, placementPointIdsThree).eq(!ObjectUtils.isEmpty(orderInfoReq.getOrderStatus()), OrderInfo::getOrderStatus, orderInfoReq.getOrderStatus()).le(StringUtils.isNotBlank(orderInfoReq.getOrderEndDate()), OrderInfo::getCreateTime, orderInfoReq.getOrderEndDate() + " " + "23:59:59").ge(StringUtils.isNotBlank(orderInfoReq.getOrderStartDate()), OrderInfo::getCreateTime, orderInfoReq.getOrderStartDate() + " " + "00:00:00").eq(OrderInfo::getPlatformCode, 2).isNotNull(OrderInfo::getPlacementPointId).orderByDesc(OrderInfo::getCreateTime);
        Page<OrderInfo> orderInfoPageList = orderInfoMapper.selectPage(new Page<>(orderInfoReq.getPage(), orderInfoReq.getSize()), wrapper);

        Set<String> placementPointIdSet = orderInfoPageList.getRecords().stream().map(OrderInfo::getPlacementPointId).collect(Collectors.toSet());

        Set<String> collect = placementPointIdSet.stream().filter(Objects::nonNull).collect(Collectors.toSet());
        if (CollectionUtils.isEmpty(collect)) {
            return RespJsonPageData.success(orderInfoResList, 0);
        }
        List<OrderInfoRes> orderInfoRes = BeanUtil.copyProperties(orderInfoPageList.getRecords(), OrderInfoRes.class);
        List<PlacementPoint> placementPointListTwo = placementPointRest.getPlacementPointListByIds(placementPointIdSet);
        Set<String> scenicSpotIdLists = placementPointListTwo.stream().map(PlacementPoint::getScenicSpotId).collect(Collectors.toSet());
        if (CollectionUtils.isEmpty(scenicSpotIdLists)) {
//            throw new RuntimeException("没有关联的景区!");
            return RespJsonPageData.success(orderInfoRes, orderInfoPageList.getTotal());
        }
        List<ScenicSpot> scenicSpotList = scenicSpotRest.selectScenicSpotListByIds(scenicSpotIdLists);
        Map<String, String> placementPointIdAndscenicSpotNameMap = new HashMap<>(10);
        placementPointListTwo.forEach(placementPoint -> scenicSpotList.forEach(scenicSpot -> {
            if (placementPoint.getScenicSpotId().equals(scenicSpot.getId())) {
                placementPointIdAndscenicSpotNameMap.put(placementPoint.getId(), scenicSpot.getName());
            }
        }));
        List<String> wayBillNoList = orderInfoPageList.getRecords().stream().map(OrderInfo::getTcWaybillNo).collect(Collectors.toList());
        List<OrderCommodity> orderCommodityList = orderCommodityRest.getByOrderSns(wayBillNoList);

        Map<String, OrderCommodity> waybillNoAndOrderCommodityMap = orderCommodityList.stream().collect(Collectors.toMap(OrderCommodity::getId, each -> each, (value1, value2) -> value1));

        Set<String> commodityIdSet = orderCommodityList.stream().map(OrderCommodity::getCommodityId).collect(Collectors.toSet());

        List<Commodity> commodities = commodityRest.selectProductByIds(commodityIdSet);

        Set<String> businessIds = commodities.stream().map(Commodity::getBusinessId).collect(Collectors.toSet());
        if (CollectionUtils.isEmpty(businessIds)) {
            return RespJsonPageData.success(orderInfoResList, 0);
        }
        List<Business> businessesList = businessRest.getBusinessesByBusinessIds(businessIds);

        Map<String, String> businessesIdAndNameMap = businessesList.stream().collect(Collectors.toMap(Business::getId, Business::getName, (value1, value2) -> value1));

        //订单号和商品名称等具体信息的集合
        IdentityHashMap<String, OrderCommodityAndBusiness> waybillNoAndCommodityMap = new IdentityHashMap<>(10);
        //商品订单信息以及商品id
        orderCommodityList.forEach(orderCommodity -> {
            //纯商品信息包含商家id商品id
            commodities.forEach(commodity -> {
                if (orderCommodity.getCommodityId().equals(commodity.getId())) {
                    OrderCommodityAndBusiness orderCommodityAndBusiness = BeanUtil.copyProperties(orderCommodity, OrderCommodityAndBusiness.class);
                    orderCommodityAndBusiness.setBusinessId(commodity.getBusinessId());
                    waybillNoAndCommodityMap.put(orderCommodity.getOrderSn(), orderCommodityAndBusiness);
                }
            });
        });

        orderInfoRes.forEach(orderInfoResc -> {
            if (StringUtils.isNotBlank(placementPointIdAndscenicSpotNameMap.get(orderInfoResc.getPlacementPointId()))) {
                orderInfoResc.setScenicSpotName(placementPointIdAndscenicSpotNameMap.get(orderInfoResc.getPlacementPointId()));
            }
            List<OrderCommodityAndBusiness> commodityList = new ArrayList<>();
            waybillNoAndCommodityMap.forEach((key, value) -> {
                if (orderInfoResc.getTcWaybillNo().equals(key)) {
                    commodityList.add(value);
                }
            });
            List<CommodityQuery> commodityQueries = BeanUtil.copyProperties(commodityList, CommodityQuery.class);

            commodityQueries.forEach(commodityQuery -> {
                if (StringUtils.isNotBlank(businessesIdAndNameMap.get(commodityQuery.getBusinessId()))) {
                    commodityQuery.setBusinessName(businessesIdAndNameMap.get(commodityQuery.getBusinessId()));

                }
                waybillNoAndOrderCommodityMap.forEach((key, value) -> {
                    if (value.getOrderSn().equals(orderInfoResc.getTcWaybillNo()) && value.getCommodityId().equals(commodityQuery.getId())) {
                        commodityQuery.setBuyCnt(value.getCnt());
                        commodityQuery.setBuyPrice(value.getPrice());
                    }
                });

            });
            orderInfoResc.setCommodityList(commodityQueries);
            orderInfoResc.setStatusName(RescueOrderStatusEnum.getName(orderInfoResc.getOrderStatus()));
            if (RescueOrderStatusEnum.COMPLETED.getStatus().equals(orderInfoResc.getOrderStatus())) {
                orderInfoResc.setUpdateTime(orderInfoResc.getUpdateTime());
            } else {
                orderInfoResc.setUpdateTime(null);
            }
        });
        return RespJsonPageData.success(orderInfoRes, orderInfoPageList.getTotal());
    }

    @Override
    public void updateStatus(UpdateStatusRequest updateStatusRequest) {
        String processedBy = updateStatusRequest.getProcessedBy();
        String orderId = updateStatusRequest.getOrderId();
        Integer status = updateStatusRequest.getOrderStatus();
        if (!status.equals(RescueOrderStatusEnum.MATERIAL_PREPARATION.getStatus()) && !status.equals(RescueOrderStatusEnum.IN_TRANSIT.getStatus()) && !status.equals(RescueOrderStatusEnum.COMPLETED.getStatus())) {
            throw new RuntimeException("只能将状态改为物资准备中、⽆⼈机运输中、已完成");
        }
        Date date = new Date();
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        if (ObjectUtils.isEmpty(orderInfo)) {
            throw new RuntimeException("订单不存在");
        }
        String userId = orderInfo.getUserId();
        Integer orderStatus = orderInfo.getOrderStatus();


        if (!RescueOrderStatusEnum.WAITING_FOR_ORDER_ACCEPTANCE.getStatus().equals(orderStatus) && !RescueOrderStatusEnum.MATERIAL_PREPARATION.getStatus().equals(orderStatus) && !RescueOrderStatusEnum.IN_TRANSIT.getStatus().equals(orderStatus)) {
            throw new RuntimeException("只能修改订单状态为等待平台接单、物资准备中、⽆⼈机运输中的订单");
        }
        if (!status.equals(orderStatus)) {
            if (status.equals(RescueOrderStatusEnum.MATERIAL_PREPARATION.getStatus())) {
                if (!orderStatus.equals(RescueOrderStatusEnum.WAITING_FOR_ORDER_ACCEPTANCE.getStatus())) {
                    throw new RuntimeException("等待平台接单的状态才能更新为物资准备中");
                } else {
                }
            } else if (status.equals(RescueOrderStatusEnum.IN_TRANSIT.getStatus())) {
                if (!orderStatus.equals(RescueOrderStatusEnum.MATERIAL_PREPARATION.getStatus())) {
                    throw new RuntimeException("物资准备中的状态才能更新为⽆⼈机运输中");
                }
            } else if (status.equals(RescueOrderStatusEnum.COMPLETED.getStatus())) {
                if (!orderStatus.equals(RescueOrderStatusEnum.IN_TRANSIT.getStatus())) {
                    throw new RuntimeException("运输中的状态才能更新为已完成");
                }
            }
            orderInfo.setOrderStatus(status);
            orderInfo.setUpdateTime(date);
            orderInfoMapper.updateById(orderInfo);
            TaskStatusLog taskStatusLog = new TaskStatusLog();
            taskStatusLog.setStatus(status);
            taskStatusLog.setTaskId(orderInfo.getId());
            taskStatusLog.setProcessedBy(processedBy);
            taskStatusLog.setCreateTime(date);
            taskStatusLog.setUpdateTime(date);
            taskStatusLog.setUserId(orderInfo.getUserId());
            taskStatusLogRest.add(taskStatusLog);
            String templateId = null;
            String accessToken = loginService.getAccessToken();
            HashMap data = new HashMap();
            String openId = (String) redisTemplate.opsForValue().get(ServicePrefixEnum.RESCUE + RedisPrefixKey.APPLET_OPENID + userId);
            //状态变更
            if (status.equals(RescueOrderStatusEnum.MATERIAL_PREPARATION.getStatus())) {
                templateId = updateStatusTemplateId;
                Map character_string1 = new HashMap();
                character_string1.put("value", orderInfo.getTcWaybillNo());
                Map phrase11 = new HashMap();
                phrase11.put("value", RescueOrderStatusEnum.getName(status));
                Map thing5 = new HashMap();
                thing5.put("value", "您的无人机订单已开始准备");
                Map date4 = new HashMap();
                date4.put("value", DateUtil.format(orderInfo.getCreateTime(), "yyyy-MM-dd HH:mm:ss"));
                data.put("character_string1", character_string1);
                data.put("phrase11", phrase11);
                data.put("thing5", thing5);
                data.put("date4", date4);
            } else if (status.equals(RescueOrderStatusEnum.IN_TRANSIT.getStatus())) {
                templateId = deliveryStartTemplateId;
                String placementPointId = orderInfo.getPlacementPointId();
                String targetAddress = "";
                if (!ObjectUtils.isEmpty(placementPointId)) {
                    PlacementPoint placementPoint = placementPointMapper.selectById(placementPointId);
                    if (!ObjectUtils.isEmpty(placementPoint)) {
                        String scenicSpotId = placementPoint.getScenicSpotId();
                        ScenicSpot scenicSpot = scenicSpotMapper.selectById(scenicSpotId);
                        if (!ObjectUtils.isEmpty(scenicSpot)) {
                            targetAddress = scenicSpot.getName() + "-" + placementPoint.getName();
                        }
                    }
                }
                Map thing2 = new HashMap(1);
                if (!ObjectUtils.isEmpty(targetAddress)) {
                    int length = targetAddress.length();
                    if (length > 20) {
                        targetAddress = targetAddress.substring(0, 16) + "...";
                    }
                    thing2.put("value", targetAddress);
                }

                Map character_string7 = new HashMap();
                character_string7.put("value", orderInfo.getTcWaybillNo());
                Map thing1 = new HashMap();
                List<OrderCommodity> orderCommodities = orderCommodityRest.getByOrderSn(orderInfo.getTcWaybillNo());
                if (!CollectionUtils.isEmpty(orderCommodities)) {
                    List<String> commodityIds = orderCommodities.stream().map(orderCommodity -> orderCommodity.getCommodityId()).collect(Collectors.toList());
                    String names = commodityMapper.selectBatchIds(commodityIds).stream().map(commodity -> commodity.getName()).collect(Collectors.joining(";"));
                    if (!ObjectUtils.isEmpty(names)) {
                        int length = names.length();
                        if (length > 20) {
                            names = names.substring(0, 16) + "...";
                        }
                        thing1.put("value", names);
                    }

                }
                Map thing5 = new HashMap();
                thing5.put("value", "请在投送点等待商品送达");
                data.put("character_string7", character_string7);
                data.put("thing1", thing1);
                data.put("thing5", thing5);
                data.put("thing2", thing2);
            } else if (status.equals(RescueOrderStatusEnum.COMPLETED.getStatus())) {
                String placementPointId = orderInfo.getPlacementPointId();
                String targetAddress = "";
                if (!ObjectUtils.isEmpty(placementPointId)) {
                    PlacementPoint placementPoint = placementPointMapper.selectById(placementPointId);
                    if (!ObjectUtils.isEmpty(placementPoint)) {
                        String scenicSpotId = placementPoint.getScenicSpotId();
                        ScenicSpot scenicSpot = scenicSpotMapper.selectById(scenicSpotId);
                        if (!ObjectUtils.isEmpty(scenicSpot)) {
                            targetAddress = scenicSpot.getName() + "-" + placementPoint.getName();
                        }
                    }
                }

                templateId = deliveryCompletedTemplateId;
                //配送完成
                Map character_string1 = new HashMap(1);
                character_string1.put("value", orderInfo.getTcWaybillNo());
                Map thing2 = new HashMap(1);
                if (!ObjectUtils.isEmpty(targetAddress)) {
                    int length = targetAddress.length();
                    if (length > 20) {
                        targetAddress = targetAddress.substring(0, 16) + "...";
                    }
                    thing2.put("value", targetAddress);
                }
                Map thing3 = new HashMap(1);
                thing3.put("value", "您的订单已由无人机安全送达~");
                JSONObject time4 = new JSONObject();
                time4.put("value", sdf.format(date));
                data.put("thing2", thing2);
                data.put("thing3", thing3);
                data.put("time4", time4);
                data.put("character_string1", character_string1);
            }
            wxAppletRest.subscribeSend(accessToken, templateId, openId, data, "packageA/pages/goodsDetail/goodsDetail?id=" + orderInfo.getId() + "&backHome=1");
        }
    }

    @Override
    public Boolean updateExpressOrderStatus(UpdateOrderInfoStatusRequest updateOrderInfoStatusRequest) {
        Integer status = updateOrderInfoStatusRequest.getOrderStatus();
        String wrongMsg = updateOrderInfoStatusRequest.getWrongMsg();
        if (10 != status && !OrderStatusEnum.PENDING_ITEMS.getStatus().equals(status) && !OrderStatusEnum.DOOR_TO_DOOR_PICKUP.getStatus().equals(status) && !OrderStatusEnum.DRONE_HAS_BEEN_PICKED_UP.getStatus().equals(status) && !OrderStatusEnum.DRONE_DELIVERY_IN_PROGRESS.getStatus().equals(status) && !OrderStatusEnum.TO_BE_DISPATCHED.getStatus().equals(status) && !OrderStatusEnum.COMPLETED.getStatus().equals(status) && !OrderStatusEnum.ABNORMAL.getStatus().equals(status) && !OrderStatusEnum.DRONE_READY_TO_TAKE_OFF.getStatus().equals(status) && !OrderStatusEnum.THE_DRONE_HAS_ARRIVED_AT_THE_TERMINAL.getStatus().equals(status)) {
            throw new RuntimeException("只能将状态修改为等待无人机接单、上门取件中、无人机已取件、无人机准备起飞、无人机配送中、无人机抵达航站、上门派送中、已完成、异常");
        }
        String tcWaybillNo = updateOrderInfoStatusRequest.getTcWaybillNo();
        Lock lock = null;
        try {

            Date date = new Date();
            QueryWrapper<OrderInfo> orderInfoQueryWrapper = new QueryWrapper<>();
            orderInfoQueryWrapper.eq("tc_waybill_no", tcWaybillNo);
            OrderInfo orderInfo = orderInfoMapper.selectOne(orderInfoQueryWrapper);
            if (ObjectUtils.isEmpty(orderInfo)) {
                throw new RuntimeException("订单不存在");
            }
            String userId = orderInfo.getUserId();
            lock = redissonClient.getLock(ServicePrefixEnum.SAME_CITY + RedisPrefixKey.UPDATE_STATUS + userId);
            //也可以指定锁时间的
            boolean b = lock.tryLock(lockTryTime, TimeUnit.SECONDS);
            if (b) {

                //业务
                Integer orderStatus = orderInfo.getOrderStatus();

                if (!OrderStatusEnum.PENDING_ITEMS.getStatus().equals(orderStatus) && !OrderStatusEnum.DOOR_TO_DOOR_PICKUP.getStatus().equals(orderStatus) && !OrderStatusEnum.DRONE_HAS_BEEN_PICKED_UP.getStatus().equals(orderStatus) && !OrderStatusEnum.DRONE_DELIVERY_IN_PROGRESS.getStatus().equals(orderStatus) && !OrderStatusEnum.TO_BE_DISPATCHED.getStatus().equals(orderStatus) && !OrderStatusEnum.DRONE_READY_TO_TAKE_OFF.getStatus().equals(orderStatus) && !OrderStatusEnum.THE_DRONE_HAS_ARRIVED_AT_THE_TERMINAL.getStatus().equals(orderStatus)) {
                    throw new RuntimeException("只能修改订单状态为待取货、上门取件中、无人机已取件、无人机准备起飞、无人机配送中、无人机已抵达航站、上门派送中的订单");
                }
                String riderName = updateOrderInfoStatusRequest.getRiderName();
                if (!ObjectUtils.isEmpty(riderName)) {
                    //只要骑手名称不为空就更新，同城和地勤派件都会传骑手名称
                    this.recordErrandOrder(updateOrderInfoStatusRequest);
                }
                if (!status.equals(orderStatus)) {

//                this.checkStatus(orderStatus, status);
                    if (OrderStatusEnum.ABNORMAL.getStatus().equals(status)) {
                        if ("取消订单".equals(wrongMsg)) {
                            //我们这边发起的取消，去平台组取消之后，平台组那边还调用我们这边的更新状态接口是多余的，这里给他终止了
                            return true;
                        }
                        if (orderStatus.equals(OrderStatusEnum.CANCEL.getStatus())) {
                            //我们这边发起的取消，去平台组取消之后，平台组那边还调用我们这边的更新状态接口是多余的，这里给他终止了
                            return true;
                        }
                        IdRequest idRequest = new IdRequest();
                        idRequest.setId(orderInfo.getId());
                        idRequest.setProcessedBy("平台组");
                        idRequest.setStatus(status);
                        idRequest.setWrongMsg(updateOrderInfoStatusRequest.getWrongMsg());
                        //这个异常是平台组那边传过来的，对应我们这边的取消
                        this.cancelExpressOrder(idRequest);
                        return true;
                    }
                    //10是同城端骑手取消
                    if (10 == status) {
                        ErrandOrder errandOrder = errandOrderController.getByOrderSn(tcWaybillNo, ErrandOrderTypeEnum.DELIVERY.getValue());
                        if (ObjectUtils.isEmpty(errandOrder)) {
                            //没有派送记录，就是收件，收件回退到等待无人机接单
                            status = OrderStatusEnum.PENDING_ITEMS.getStatus();
                            errandOrder = errandOrderController.getByOrderSn(tcWaybillNo, ErrandOrderTypeEnum.COLLECTING.getValue());
                        } else {
                            //有派送记录就是派件，派件回退到无人机已抵达航站
                            status = OrderStatusEnum.THE_DRONE_HAS_ARRIVED_AT_THE_TERMINAL.getStatus();
                        }
                        if (!ObjectUtils.isEmpty(errandOrder)) {
                            //更新骑手订单的骑手订单状态
                            errandOrder.setStatus(TcOrderStatusEnum.ORDER_CANCELED.getStatus().byteValue());
                            errandOrder.setUpdateTime(date);
                            errandOrder.setErrandOrderSn(null);
                            errandOrderMapper.updateById(errandOrder);
                        }
                    }

                    orderInfo.setOrderStatus(status);
                    orderInfo.setUpdateTime(date);
                    orderInfoMapper.updateById(orderInfo);
                    TaskStatusLog taskStatusLog = new TaskStatusLog();
                    taskStatusLog.setStatus(status);
                    taskStatusLog.setProcessedBy(updateOrderInfoStatusRequest.getProcessedBy());
                    taskStatusLog.setTaskId(orderInfo.getId());
                    taskStatusLog.setCreateTime(date);
                    taskStatusLog.setUpdateTime(date);
                    taskStatusLog.setUserId(orderInfo.getUserId());
                    taskStatusLogRest.add(taskStatusLog);
                    String accessToken = loginService.getExpressAccessToken();
                    String templateId;
                    HashMap data = new HashMap();
                    String openId = (String) redisTemplate.opsForValue().get(ServicePrefixEnum.SAME_CITY + RedisPrefixKey.APPLET_OPENID + orderInfo.getUserId());

                    //状态变更
                    if (status.equals(OrderStatusEnum.DOOR_TO_DOOR_PICKUP.getStatus())) {
                        //通知变更
                        templateId = updateExpressStatusTemplateId;
                        String orderId = orderInfo.getId();
                        String goodsTypeId = orderInfo.getGoodsTypeId();
                        //状态变更
                        Map character_string13 = new HashMap();
                        character_string13.put("value", tcWaybillNo);
                        Map phrase3 = new HashMap();
                        phrase3.put("value", OrderStatusEnum.getName(status));
                        Map thing18 = new HashMap();
                        CityGoodsType cityGoodsType = cityGoodsTypeMapper.selectById(goodsTypeId);
                        thing18.put("value", ObjectUtils.isEmpty(cityGoodsType) ? "--" : cityGoodsType.getName());
                        Map thing4 = new HashMap();
                        thing4.put("value", "小主，小哥正在马不停蹄的赶来~");
                        data.put("character_string13", character_string13);
                        data.put("phrase3", phrase3);
                        data.put("thing18", thing18);
                        data.put("thing4", thing4);
                        wxAppletRest.subscribeSend(accessToken, templateId, openId, data, "pages/tasks/details/details?taskId=" + orderId + "&backHome=1");
                    } else if (status.equals(OrderStatusEnum.DRONE_READY_TO_TAKE_OFF.getStatus())) {
                        //记录同城订单完成
                        this.updateCompleted(tcWaybillNo, ErrandOrderTypeEnum.COLLECTING.getValue());
                    } else if (status.equals(OrderStatusEnum.TO_BE_DISPATCHED.getStatus())) {
                        templateId = deliveryStartTemplateId;
                        //配送完成
                        Map character_string1 = new HashMap();
                        character_string1.put("value", orderInfo.getTcWaybillNo());
                        Map thing2 = new HashMap();
                        String receiveAddressName = orderInfo.getReceiveAddressName();
                        if (!ObjectUtils.isEmpty(receiveAddressName)) {
                            int length = receiveAddressName.length();
                            if (length > 20) {
                                receiveAddressName = receiveAddressName.substring(0, 16) + "...";
                            }
                            thing2.put("value", receiveAddressName);
                        }
                        Map thing3 = new HashMap(1);
                        thing3.put("value", "无人机已抵达，小哥上门派送中~");
                        JSONObject time4 = new JSONObject();
                        time4.put("value", sdf.format(orderInfo.getUpdateTime()));
                        data.put("character_string1", character_string1);
                        data.put("thing2", thing2);
                        data.put("thing3", thing3);
                        data.put("time4", time4);
                        wxAppletRest.subscribeSend(accessToken, templateId, openId, data, "pages/tasks/details/details?taskId=" + orderInfo.getId() + "&backHome=1");
                    } else if (status.equals(OrderStatusEnum.COMPLETED.getStatus())) {
                        QueryWrapper<InvitationRecord> invitationRecordQueryWrapper = new QueryWrapper<>();
                        invitationRecordQueryWrapper.eq("user_id", userId);
                        InvitationRecord invitationRecord = invitationRecordMapper.selectOne(invitationRecordQueryWrapper);
                        if (!ObjectUtils.isEmpty(invitationRecord)) {
                            String invitationCodeId = invitationRecord.getInvitationCodeId();
                            InvitationCode invitationCode = invitationCodeMapper.selectById(invitationCodeId);
                            if (!ObjectUtils.isEmpty(invitationCode)) {
                                String activityId = invitationCode.getActivityId();
                                //判断是否同城
                                Byte productType = orderInfo.getOrderType();
                                ActivityRewardRules activityRewardRules = activityRest.getSettingsByProductType(productType, activityId);
                                if (!ObjectUtils.isEmpty(activityRewardRules)) {
                                    QueryWrapper<PromotionRecords> promotionRecordsQueryWrapper = new QueryWrapper<>();
                                    promotionRecordsQueryWrapper.eq("payer_user_id", userId);
                                    promotionRecordsQueryWrapper.eq("activity_id", activityId);
                                    promotionRecordsQueryWrapper.isNull("promotion_reward");
                                    promotionRecordsQueryWrapper.eq("tc_waybill_no", tcWaybillNo);
                                    PromotionRecords promotionRecords = promotionRecordsMapper.selectOne(promotionRecordsQueryWrapper);
                                    if (!ObjectUtils.isEmpty(promotionRecords)) {
                                        String invitationUserId = promotionRecords.getPromotionUserId();
                                        BigDecimal rewardAmount = activityRewardRules.getRewardAmount();
                                        if (orderInfo.getPricePaid().compareTo(rewardAmount) >= 0) {
                                            promotionRecords.setPromotionReward(rewardAmount);
                                            promotionRecords.setRewardType(productType);
                                            promotionRecords.setUpdateTime(date);
                                            promotionRecords.setFinishTime(date);
                                            promotionRecordsMapper.updateById(promotionRecords);

                                            //处理统计数据
                                            PromotionStatistics promotionStatistics = promotionStatisticsRest.getPromotionStatistics(invitationUserId, activityId);
                                            if (!ObjectUtils.isEmpty(promotionStatistics)) {
                                                promotionStatistics.setUpdateTime(date);
                                                promotionStatistics.setPromotionOrderQuantity(promotionStatistics.getPromotionOrderQuantity() + 1);
                                                promotionStatistics.setTotalReward(promotionStatistics.getTotalReward().add(rewardAmount));
                                                promotionStatisticsMapper.updateById(promotionStatistics);
                                            }
                                            UserWallet userWallet = userWalletRest.selectOneByUserId(invitationUserId);
                                            if (ObjectUtils.isEmpty(userWallet)) {
                                                userWallet = new UserWallet();
                                                userWallet.setCreateTime(date);
                                                userWallet.setUpdateTime(date);
                                                userWallet.setUserId(invitationUserId);
                                                userWallet.setBalance(rewardAmount);
                                                userWallet.setAccumulatedRewards(rewardAmount);
                                                userWalletMapper.insert(userWallet);
                                            } else {
                                                userWallet.setUpdateTime(date);
                                                userWallet.setBalance(userWallet.getBalance().add(rewardAmount));
                                                userWallet.setAccumulatedRewards(userWallet.getAccumulatedRewards().add(rewardAmount));
                                                userWalletMapper.updateById(userWallet);
                                            }

                                            RewardBill rewardBill = new RewardBill();
                                            rewardBill.setCreateTime(date);
                                            rewardBill.setUpdateTime(date);
                                            rewardBill.setUserId(invitationUserId);
                                            rewardBill.setBalance(userWallet.getBalance());
                                            rewardBill.setRewardType(RewardTypeEnum.TRANSACTION_REWARD.getType());
                                            rewardBill.setPricePaid(rewardAmount);
                                            rewardBill.setType(BillTypeEnum.INCOME.getValue());
                                            rewardBill.setTcWaybillNo(orderInfo.getTcWaybillNo());
                                            rewardBillMapper.insert(rewardBill);
                                        }
                                    }
                                }
                            }
                        }
                        //更新派送同城订单胡状态为已完成
                        this.updateCompleted(tcWaybillNo, ErrandOrderTypeEnum.DELIVERY.getValue());
                    }
                    return true;
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (!ObjectUtils.isEmpty(lock)) {
                // 释放锁
                lock.unlock();
            }
        }
        return false;

    }


    public void updateCompleted(String orderSn, Byte type) {
        ErrandOrder errandOrder = errandOrderController.getByOrderSn(orderSn, type);
        if (!ObjectUtils.isEmpty(errandOrder)) {
            errandOrder.setUpdateTime(new Date());
            errandOrder.setStatus(TcOrderStatusEnum.DELIVERYMAN_DELIVERY_COMPLETED.getStatus().byteValue());
            errandOrderMapper.updateById(errandOrder);
        }
    }


    public void cancelErrandOrder(String orderSn) {
        ErrandOrder errandOrder = errandOrderController.getByOrderSn(orderSn, ErrandOrderTypeEnum.COLLECTING.getValue());
        if (!ObjectUtils.isEmpty(errandOrder)) {
            errandOrder.setStatus(TcOrderStatusEnum.ORDER_CANCELED.getStatus().byteValue());
            errandOrder.setUpdateTime(new Date());
            errandOrderMapper.updateById(errandOrder);
        }
    }


    public void recordErrandOrder(UpdateOrderInfoStatusRequest updateOrderInfoStatusRequest) {
        String orderSn = updateOrderInfoStatusRequest.getTcWaybillNo();
        Integer orderStatus = updateOrderInfoStatusRequest.getOrderStatus();
        String errandOrderSn = updateOrderInfoStatusRequest.getErrandOrderSn();
        String riderName = updateOrderInfoStatusRequest.getRiderName();
        String submitPhotoUrl = updateOrderInfoStatusRequest.getSubmitPhotoUrl();
        ErrandOrder errandOrder = iErrandOrderService.getByErrandOrderSn(errandOrderSn);
        String riderPhone = updateOrderInfoStatusRequest.getRiderPhone();
        Date date = new Date();
        if (ObjectUtils.isEmpty(errandOrder)) {
            //查看是否有旧的，旧的就覆盖
            if (Arrays.asList(OrderStatusEnum.PENDING_ITEMS.getStatus(), OrderStatusEnum.DOOR_TO_DOOR_PICKUP.getStatus(), OrderStatusEnum.DRONE_HAS_BEEN_PICKED_UP.getStatus()).contains(orderStatus)) {
                //收件
                errandOrder = errandOrderController.getByOrderSn(orderSn, ErrandOrderTypeEnum.COLLECTING.getValue());
            } else {
                //派件
                errandOrder = errandOrderController.getByOrderSn(orderSn, ErrandOrderTypeEnum.DELIVERY.getValue());
            }
        }
        if (ObjectUtils.isEmpty(errandOrder)) {
            errandOrder = BeanUtil.copyProperties(updateOrderInfoStatusRequest, ErrandOrder.class);
            ErrandOrder colletingErrandOrder = errandOrderController.getByOrderSn(orderSn, ErrandOrderTypeEnum.COLLECTING.getValue());
            if (ObjectUtils.isEmpty(colletingErrandOrder)) {
                //没收的先创建收的
                errandOrder.setType(ErrandOrderTypeEnum.COLLECTING.getValue());
            } else {
                errandOrder.setType(ErrandOrderTypeEnum.DELIVERY.getValue());
            }
            if (!ObjectUtils.isEmpty(riderPhone)) {
                if (riderPhone.length() == 11) {
                    riderPhone = phoneEncoderUtil.encryptString(riderPhone);
                }
            }
            errandOrder.setRiderPhone(riderPhone);
            errandOrder.setOrderSn(orderSn);
            errandOrder.setUpdateTime(date);
            errandOrder.setCreateTime(date);
            errandOrderMapper.insert(errandOrder);
        } else {
            errandOrder.setUpdateTime(date);
            errandOrder.setStatus(updateOrderInfoStatusRequest.getStatus());

            if (!ObjectUtils.isEmpty(riderName)) {
                errandOrder.setRiderName(riderName);
            }
            if (!ObjectUtils.isEmpty(errandOrderSn)) {
                errandOrder.setErrandOrderSn(errandOrderSn);
            }
            if (!ObjectUtils.isEmpty(submitPhotoUrl)) {
                errandOrder.setSubmitPhotoUrl(submitPhotoUrl);
            }
            if (!ObjectUtils.isEmpty(riderPhone)) {
                if (riderPhone.length() == 11) {
                    riderPhone = phoneEncoderUtil.encryptString(riderPhone);
                }
                errandOrder.setRiderPhone(riderPhone);
            }
            errandOrder.setLongitude(updateOrderInfoStatusRequest.getLongitude());
            errandOrder.setLatitude(updateOrderInfoStatusRequest.getLatitude());
            errandOrderMapper.updateById(errandOrder);
        }
    }

    private void checkStatus(Integer startStatus, Integer endStatus) {
        if (startStatus.equals(OrderStatusEnum.PENDING_ITEMS.getStatus())) {
            if (!endStatus.equals(OrderStatusEnum.DOOR_TO_DOOR_PICKUP.getStatus())) {
                throw new RuntimeException("状态变更逻辑不对");
            }
        } else if (startStatus.equals(OrderStatusEnum.DOOR_TO_DOOR_PICKUP.getStatus())) {
            if (!endStatus.equals(OrderStatusEnum.DRONE_HAS_BEEN_PICKED_UP.getStatus())) {
                throw new RuntimeException("状态变更逻辑不对");
            }
        } else if (startStatus.equals(OrderStatusEnum.DRONE_HAS_BEEN_PICKED_UP.getStatus())) {
            if (!endStatus.equals(OrderStatusEnum.DRONE_DELIVERY_IN_PROGRESS.getStatus())) {
                throw new RuntimeException("状态变更逻辑不对");
            }
        } else if (startStatus.equals(OrderStatusEnum.DRONE_DELIVERY_IN_PROGRESS.getStatus())) {
            if (!endStatus.equals(OrderStatusEnum.TO_BE_DISPATCHED.getStatus())) {
                throw new RuntimeException("状态变更逻辑不对");
            }
        } else if (startStatus.equals(OrderStatusEnum.TO_BE_DISPATCHED.getStatus())) {
            if (!endStatus.equals(OrderStatusEnum.COMPLETED.getStatus())) {
                throw new RuntimeException("状态变更逻辑不对");
            }
        }
    }

    @Override
    public ScenicSpotOrderDetailRes getScenicSpotOrderDetail(String tcWaybillNo) {
        if (StringUtils.isBlank(tcWaybillNo)) {
            throw new RuntimeException("订单编号不能为空!");
        }
        OrderInfo orderInfo = orderInfoMapper.selectOne(new QueryWrapper<OrderInfo>().eq("tc_waybill_no", tcWaybillNo).eq("platform_code", 2));
        if (!ObjectUtils.isEmpty(orderInfo) && StringUtils.isBlank(orderInfo.getPlacementPointId())) {
            throw new RuntimeException("该订单没有投放点!");
        }
        ScenicSpotOrderDetailRes scenicSpotOrderDetailRes = BeanUtil.copyProperties(orderInfo, ScenicSpotOrderDetailRes.class);
        scenicSpotOrderDetailRes.setOrderStatusName(RescueOrderStatusEnum.getName(scenicSpotOrderDetailRes.getOrderStatus()));
        List<TaskStatusLog> taskStatusLogs = taskStatusLogRest.selectListByTaskId(orderInfo.getId());
        Map<Integer, Date> taskStatusLogsMap = taskStatusLogs.stream().collect(Collectors.toMap(TaskStatusLog::getStatus, TaskStatusLog::getCreateTime, (value1, value2) -> value1));
        PlacementPoint placementPoint = placementPointRest.selectByIdNoByStatus(orderInfo.getPlacementPointId());
        if (ObjectUtils.isEmpty(placementPoint)) {
            throw new RuntimeException("该订单没有投放点!");
        }
        ScenicSpot scenicSpot = scenicSpotRest.selectById(placementPoint.getScenicSpotId());
        scenicSpotOrderDetailRes.setScenicSpotName(scenicSpot.getName());
        List<OrderCommodity> orderCommodityList = orderCommodityRest.getByOrderSn(orderInfo.getTcWaybillNo());
        List<OrderCommodityAndBusiness> orderCommodityAndBusinesses = BeanUtil.copyProperties(orderCommodityList, OrderCommodityAndBusiness.class);
        Set<String> commodityIdSet = orderCommodityList.stream().map(OrderCommodity::getCommodityId).collect(Collectors.toSet());
        //查到的该订单下正确的商品商家的关联关系表
        List<Commodity> commodities = commodityRest.selectProductByIds(commodityIdSet);
        Map<String, String> commIdAndNameMap = commodities.stream().collect(Collectors.toMap(Commodity::getId, Commodity::getBusinessId));
        //取出所有关联该订单商家id的集合
        Set<String> businessIds = commodities.stream().map(Commodity::getBusinessId).collect(Collectors.toSet());
        //根据所有关联该订单号下的商家id的集合查询出商家名称及品牌关联关系表
        List<Business> businessesList = businessRest.getBusinessesByBusinessIds(businessIds);
        Map<String, String> businessIdAndName = businessesList.stream().collect(Collectors.toMap(Business::getId, Business::getName));
        orderCommodityAndBusinesses.forEach(orderCommodityAndBusiness -> {
            if (StringUtils.isNotBlank(commIdAndNameMap.get(orderCommodityAndBusiness.getCommodityId()))) {
                orderCommodityAndBusiness.setBusinessId(commIdAndNameMap.get(orderCommodityAndBusiness.getCommodityId()));
            }
        });
        //拷贝orderCommodityList原来的订单商品关联关系表的数据到需要返回给前端的实体类中
        List<CommodityQuery> commodityQueries = BeanUtil.copyProperties(orderCommodityAndBusinesses, CommodityQuery.class);
        commodityQueries.forEach(commodityQu -> {
            commodityQu.setBusinessName(businessIdAndName.get(commodityQu.getBusinessId()));
        });
        scenicSpotOrderDetailRes.setCommodityList(commodityQueries);
        scenicSpotOrderDetailRes.setPlacementPointName(placementPoint.getName());
        scenicSpotOrderDetailRes.setOrderReceivingTime(taskStatusLogsMap.get(RescueOrderStatusEnum.MATERIAL_PREPARATION.getStatus()));
        scenicSpotOrderDetailRes.setDepartureTime(taskStatusLogsMap.get(RescueOrderStatusEnum.IN_TRANSIT.getStatus()));
        if (StringUtils.isNotBlank(scenicSpotOrderDetailRes.getReceiverTel())) {
            scenicSpotOrderDetailRes.setReceiverTel(DesensitizedUtil.desensitized(phoneEncoderUtil.decryptString(scenicSpotOrderDetailRes.getReceiverTel()), DesensitizedUtil.DesensitizedType.MOBILE_PHONE));
        }
        if (RescueOrderStatusEnum.COMPLETED.getStatus().equals(scenicSpotOrderDetailRes.getOrderStatus())) {
            scenicSpotOrderDetailRes.setUpdateTime(scenicSpotOrderDetailRes.getUpdateTime());
        } else {
            scenicSpotOrderDetailRes.setUpdateTime(null);
        }
        return scenicSpotOrderDetailRes;
    }

    private List<OrderResponse> dto(List<OrderInfo> orderInfos) {
        List<OrderResponse> orderResponses = new ArrayList<>();
        if (!CollectionUtils.isEmpty(orderInfos)) {
            List<String> orderInfoIds = orderInfos.stream().map(orderInfo -> orderInfo.getId()).collect(Collectors.toList());
            QueryWrapper<TaskGoods> taskGoodsQueryWrapper = new QueryWrapper<>();
            taskGoodsQueryWrapper.in("task_id", orderInfoIds);
            List<TaskGoods> taskGoods = taskGoodsMapper.selectList(taskGoodsQueryWrapper);

            QueryWrapper<CityGoodsType> cityGoodsTypeQueryWrapper = new QueryWrapper<>();
            List<CityGoodsType> cityGoodsTypes = cityGoodsTypeMapper.selectList(cityGoodsTypeQueryWrapper);
            List<String> senderTels = orderInfos.stream().map(orderInfo -> orderInfo.getSenderTel()).collect(Collectors.toList());
            List<String> receiverTels = orderInfos.stream().map(orderInfo -> orderInfo.getReceiverTel()).collect(Collectors.toList());
            senderTels.addAll(receiverTels);
            Map<String, String> stringStringMap = batchDecryptionUtils.batchDecryption(senderTels);
            orderInfos.forEach(orderInfo -> {
                if (orderInfo.getOrderStatus().equals(OrderStatusEnum.TO_BE_PAID.getStatus())) {
                    if (orderInfo.getExpireTime().getTime() <= System.currentTimeMillis()) {
                        orderInfo.setOrderStatus(OrderStatusEnum.EXPIRE.getStatus());
                        Date date = new Date();
                        orderInfo.setUpdateTime(date);
                        orderInfoMapper.updateById(orderInfo);
                    }
                }
                String senderTel = orderInfo.getSenderTel();
                String receiverTel = orderInfo.getReceiverTel();

                for (Map.Entry<String, String> entry : stringStringMap.entrySet()) {
                    if (entry.getKey().equals(senderTel)) {
                        orderInfo.setSenderTel(entry.getValue());
                    }
                    if (entry.getKey().equals(receiverTel)) {
                        orderInfo.setReceiverTel(entry.getValue());
                    }
                }
                OrderResponse orderResponse = BeanUtil.copyProperties(orderInfo, OrderResponse.class);
                List<TaskGoods> taskGoodsList = taskGoods.stream().filter(taskGoods1 -> taskGoods1.getTaskId().equals(orderInfo.getId())).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(taskGoodsList)) {
                    List<CityGoodsType> goodsTypes1 = cityGoodsTypes.stream().filter(cityGoodsType -> cityGoodsType.getId().equals(taskGoodsList.get(0).getGoodsTypeId())).collect(Collectors.toList());
                    if (!CollectionUtils.isEmpty(goodsTypes1)) {
                        orderResponse.setGoodsTypeName(goodsTypes1.get(0).getName());
                    }
                }
                orderResponses.add(orderResponse);
            });


        }
        return orderResponses;
    }

    /**
     * 方法3 求两个集合交集（map）
     *
     * @param list1
     * @param list2
     * @return
     */
    public Set<String> intersectionForList3(Set<String> list1, Set<String> list2) {
        long startTime = System.currentTimeMillis();

        Set<String> resultList = new HashSet<>();
        Map<String, String> map = new HashMap<>();
        list1.forEach(a1 -> {
            map.put(a1 + "", a1);
        });

        list2.forEach(a2 -> {
            String obj = map.get(a2 + "");
            if (StringUtils.isNotBlank(obj)) {
                resultList.add(obj);
            }
        });

        long endTime = System.currentTimeMillis();
        System.out.println("intersectionForList3：" + (endTime - startTime));
        return resultList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Date cancelOrder(String id) {
        Date date = new Date();
        OrderInfo orderInfo = orderInfoMapper.selectById(id);
        if (ObjectUtils.isEmpty(orderInfo)) {
            throw new RuntimeException("订单不存在");
        }
        Integer orderStatus = orderInfo.getOrderStatus();
        if (!orderStatus.equals(RescueOrderStatusEnum.TO_BE_PAID.getStatus()) && !orderStatus.equals(RescueOrderStatusEnum.WAITING_FOR_ORDER_ACCEPTANCE.getStatus()) && !orderStatus.equals(RescueOrderStatusEnum.MATERIAL_PREPARATION.getStatus())) {
            throw new BusinessException(ErrorEnum.NOT_WAIT_PAY_OR_ORDER_ACCEPTANCE);
        }
        if (orderStatus.equals(RescueOrderStatusEnum.WAITING_FOR_ORDER_ACCEPTANCE.getStatus()) || orderStatus.equals(RescueOrderStatusEnum.MATERIAL_PREPARATION.getStatus())) {
            //1.查询是否退款过 2.退款 =》顺序不能调换
            String tradeNo = orderInfo.getTradeNo();
            if (!ObjectUtils.isEmpty(tradeNo)) {
                TradeRefundQueryRequest tradeRefundQueryRequest = new TradeRefundQueryRequest();
                tradeRefundQueryRequest.setOutRefundNo(orderInfo.getTradeNo());
                TradeRefundQueryResponse tradeRefundQueryResponse = OpenClient.request(tradeRefundQueryRequest);
                //无退款记录，T30007表示没有查询到数据
                if (tradeRefundQueryResponse.getCode().equals("90000") && tradeRefundQueryResponse.getResultCode().equals("T30007")) {
                    TradeRefundApplyRequest tradeRefundApplyRequest = new TradeRefundApplyRequest();
                    tradeRefundApplyRequest.setOutTradeNo(orderInfo.getTcWaybillNo());
                    tradeRefundApplyRequest.setNotifyUrl(callbackUrl + refundConfirmUrl);
                    logger.info("回调url{}", callbackUrl + refundConfirmUrl);
                    tradeRefundApplyRequest.setOutRefundNo(orderInfo.getTradeNo());
                    tradeRefundApplyRequest.setRefundAmount(orderInfo.getPricePaid().multiply(new BigDecimal(100)).longValue());
                    tradeRefundApplyRequest.setRefundDesc("退款");
                    TradeRefundApplyResponse tradeRefundApplyResponse = OpenClient.request(tradeRefundApplyRequest);
                    logger.info("tradeRefundApplyResponse:{}", tradeRefundApplyResponse.toString());
                    if (!tradeRefundApplyResponse.getCode().equals("00000")) {
                        throw new RuntimeException(tradeRefundApplyResponse.getResultMsg());
                    }
                    //在这里才是退款成功了
                    BillAddRequest billAddRequest = new BillAddRequest();
                    billAddRequest.setOrderId(orderInfo.getId());
                    billAddRequest.setTcWaybillNo(orderInfo.getTcWaybillNo());
                    billAddRequest.setPricePaid(orderInfo.getPricePaid());
                    billAddRequest.setPayStatus(PayStatusEnum.REFUNDING.getValue());
                    billAddRequest.setUpdateTime(date);
                    billAddRequest.setUserId(orderInfo.getUserId());
                    billAddRequest.setType(OrderTypeEnum.REFUND.getValue());
                    billRest.add(billAddRequest);
                }
            }
        }
        TaskStatusLog taskStatusLog = new TaskStatusLog();

        if (orderStatus.equals(RescueOrderStatusEnum.TO_BE_PAID.getStatus())) {
            orderInfo.setOrderStatus(RescueOrderStatusEnum.CANCEL_BEFORE_PAYMENT.getStatus());
            taskStatusLog.setStatus(RescueOrderStatusEnum.CANCEL_BEFORE_PAYMENT.getStatus());
        } else if (orderStatus.equals(RescueOrderStatusEnum.WAITING_FOR_ORDER_ACCEPTANCE.getStatus()) || orderStatus.equals(RescueOrderStatusEnum.MATERIAL_PREPARATION.getStatus())) {
            orderInfo.setOrderStatus(RescueOrderStatusEnum.CANCEL.getStatus());
            taskStatusLog.setStatus(RescueOrderStatusEnum.CANCEL.getStatus());
        }

        //恢复库存
        this.restoreInventory(orderInfo.getTcWaybillNo());

        orderInfo.setUpdateTime(date);
//        orderInfo.setType(OrderTypeEnum.REFUND.getValue());
        orderInfoMapper.updateById(orderInfo);

        taskStatusLog.setTaskId(orderInfo.getId());
        taskStatusLog.setCreateTime(date);
        taskStatusLog.setUpdateTime(date);
        taskStatusLog.setUserId(orderInfo.getUserId());
        taskStatusLogRest.add(taskStatusLog);
        return date;
    }

    @Override
    public Date cancelExpressOrder(IdRequest idRequest) {
        logger.info("进入取消流程");
        logger.info(RootContext.getXID());
        String id = idRequest.getId();
        String processedBy = idRequest.getProcessedBy();
        String wrongMsg = idRequest.getWrongMsg();
        Lock lock = null;
        try {
            lock = redissonClient.getLock(ServicePrefixEnum.SAME_CITY + RedisPrefixKey.APPLET_INVENTORY_CHANGE + id);
            //也可以指定锁时间的
            boolean b = lock.tryLock(0, TimeUnit.SECONDS);
            if (b) {
                Date date = new Date();
                OrderInfo orderInfo = orderInfoMapper.selectById(id);
                Integer orderStatus = orderInfo.getOrderStatus();
                String tcWaybillNo = orderInfo.getTcWaybillNo();
                Integer platformCode = orderInfo.getPlatformCode();
                if (ObjectUtils.isEmpty(orderInfo)) {
                    throw new RuntimeException("订单不存在");
                } else {
                    if (!orderStatus.equals(OrderStatusEnum.TO_BE_PAID.getStatus()) && !orderStatus.equals(OrderStatusEnum.PENDING_ITEMS.getStatus()) && !orderStatus.equals(OrderStatusEnum.DOOR_TO_DOOR_PICKUP.getStatus())) {
                        throw new BusinessException(ErrorEnum.NOT_WAIT_PAY_OR_PENDING_OR_PICKUP);
                    }
                }
//            if (orderStatus.equals(OrderStatusEnum.DOOR_TO_DOOR_PICKUP.getStatus())) {
//                //去同城取消订单
//                ErrandOrder errandOrder = errandOrderController.getByOrderSn(tcWaybillNo, ErrandOrderTypeEnum.COLLECTING.getValue());
//                if (!ObjectUtils.isEmpty(errandOrder)) {
//                    sysTcRest.cancelOrder(errandOrder.getErrandOrderSn());
//                }
//            }
                if (orderStatus.equals(OrderStatusEnum.PENDING_ITEMS.getStatus()) || orderStatus.equals(OrderStatusEnum.DOOR_TO_DOOR_PICKUP.getStatus())) {
                    //1.先让运控平台取消 2.查询是否退款过 3.退款 =》顺序不能调换
                    if (!orderStatus.equals(OrderStatusEnum.TO_BE_PAID.getStatus())) {
                        //向平台组下单时没有异常且不是待付款状态，才需要向平台组取消订单，待付款是不会向平台组下单的
                        //付款后，如果向平台组下单成功就会显示【上门取件中】，否则会是等待无人机接单
                        Integer status = idRequest.getStatus();
                        //如果是异常是是平台组那边 发起的取消，那么平台组那边已经取消了，不用再去取消
                        if (!OrderStatusEnum.ABNORMAL.getStatus().equals(status)) {
                            CancelWaybillRequest cancelWaybillRequest = new CancelWaybillRequest();
                            cancelWaybillRequest.setTcWaybillNo(tcWaybillNo);
                            cancelWaybillRequest.setCancelReason("取消订单");
                            JSONObject jsonObject = intraCityRest.cancelWaybill(cancelWaybillRequest);
                            if (!jsonObject.getBoolean("success")) {
                                logger.info(jsonObject.getString("errorMessage"));
//                            throw new RuntimeException(jsonObject.getString("errorMessage"));
                            }
                            //也要取消更新骑手订单记录状态为取消
                            this.cancelErrandOrder(tcWaybillNo);
                        }
                    }
                    String tradeNo = orderInfo.getTradeNo();
                    Bill bill = billRest.getByTcWaybillNoAndType(tcWaybillNo, BillTypeEnum.INCOME.getValue());
                    if (!ObjectUtils.isEmpty(bill)) {
                        if (PlatformCodeEnum.MONTHLY_SETTLEMENT_PLATFORM.getCode().equals(platformCode) && bill.getPayStatus().equals(PayStatusEnum.TO_BE_SETTLED.getValue())) {
                            //待结算的支付状态才可以这样简单取消，如果是已结算还要安排退款，具体如何做应该问清楚，针对已经结算的
                            //恢复额度
                            this.restoreCreditLimit(orderInfo.getPricePaid(), orderInfo.getUserId());
                            BillAddRequest billAddRequest = new BillAddRequest();
                            billAddRequest.setPayStatus(PayStatusEnum.CANCEL.getValue());
                            setBillAddReq(billAddRequest, orderInfo, date);
                            //收入记录的待结算改为取消
                            bill.setUpdateTime(date);
                            bill.setPayStatus(PayStatusEnum.CANCEL.getValue());
                            billMapper.updateById(bill);
                        } else if (!ObjectUtils.isEmpty(tradeNo)) {
                            //支付成功状态才让退款
                            TradeRefundQueryRequest tradeRefundQueryRequest = new TradeRefundQueryRequest();
                            tradeRefundQueryRequest.setOutRefundNo(orderInfo.getTradeNo());
                            //查询是否已经退款过
                            TradeRefundQueryResponse tradeRefundQueryResponse = OpenClient.request(tradeRefundQueryRequest);
                            //无退款记录，T30007表示没有查询到数据
                            if (tradeRefundQueryResponse.getCode().equals("90000") && tradeRefundQueryResponse.getResultCode().equals("T30007")) {
                                TradeRefundApplyRequest tradeRefundApplyRequest = new TradeRefundApplyRequest();
                                tradeRefundApplyRequest.setOutTradeNo(tcWaybillNo);
                                tradeRefundApplyRequest.setNotifyUrl(callbackUrl + refundConfirmUrl);
                                logger.info("回调url{}", callbackUrl + refundConfirmUrl);
                                tradeRefundApplyRequest.setOutRefundNo(orderInfo.getTradeNo());
                                tradeRefundApplyRequest.setRefundAmount(orderInfo.getPricePaid().multiply(new BigDecimal(100)).longValue());
                                tradeRefundApplyRequest.setRefundDesc("退款");
                                //去退款
                                TradeRefundApplyResponse tradeRefundApplyResponse = OpenClient.request(tradeRefundApplyRequest);
                                logger.info("tradeRefundApplyResponse:{}", tradeRefundApplyResponse.toString());
                                if (!tradeRefundApplyResponse.getCode().equals("00000")) {
                                    throw new RuntimeException(tradeRefundApplyResponse.getResultMsg());
                                }
                                BillAddRequest billAddRequest = new BillAddRequest();
                                billAddRequest.setPayStatus(PayStatusEnum.REFUNDING.getValue());
                                setBillAddReq(billAddRequest, orderInfo, date);
                            }
                        }
                    }
                }
                if (!ObjectUtils.isEmpty(wrongMsg)) {
                    //记录取消原因如果有的话
                    orderInfo.setWrongMsg(wrongMsg);
                }
                if (PlatformCodeEnum.MONTHLY_SETTLEMENT_PLATFORM.getCode().equals(platformCode)) {
                    orderInfo.setOrderStatus(OrderStatusEnum.CANCEL_BEFORE_PAYMENT.getStatus());
                    TaskStatusLog taskStatusLog = new TaskStatusLog();
                    taskStatusLog.setStatus(OrderStatusEnum.CANCEL_BEFORE_PAYMENT.getStatus());
                    setOrderInfoAndTaskStatusLog(taskStatusLog, orderInfo, date, processedBy);
                } else {
                    TaskStatusLog taskStatusLog = new TaskStatusLog();
                    if (orderStatus.equals(OrderStatusEnum.TO_BE_PAID.getStatus())) {
                        orderInfo.setOrderStatus(OrderStatusEnum.CANCEL_BEFORE_PAYMENT.getStatus());
                        taskStatusLog.setStatus(OrderStatusEnum.CANCEL_BEFORE_PAYMENT.getStatus());
                    } else if (orderStatus.equals(OrderStatusEnum.PENDING_ITEMS.getStatus()) || orderStatus.equals(OrderStatusEnum.DOOR_TO_DOOR_PICKUP.getStatus())) {
                        orderInfo.setOrderStatus(OrderStatusEnum.CANCEL.getStatus());
                        taskStatusLog.setStatus(OrderStatusEnum.CANCEL.getStatus());
                    }
                    String userCouponId = orderInfo.getUserCouponId();
                    if (!ObjectUtils.isEmpty(userCouponId)) {
                        UserCoupon userCoupon = userCouponMapper.selectById(userCouponId);
                        if (UserCouponStatusEnum.USED.getValue().equals(userCoupon.getStatus())) {
                            userCoupon.setStatus(UserCouponStatusEnum.NOT_USED.getValue());
                            userCoupon.setUseTime(null);
                            userCoupon.setUpdateTime(date);
                            userCouponMapper.updateById(userCoupon);
                            String couponId = userCoupon.getCouponId();
                            Coupon coupon = couponMapper.selectById(couponId);
                            if (!ObjectUtils.isEmpty(coupon)) {
                                coupon.setUsedNum(coupon.getUsedNum() - 1);
                                couponMapper.updateById(coupon);
                            }
                        }
                    }
                    setOrderInfoAndTaskStatusLog(taskStatusLog, orderInfo, date, processedBy);
                }
                return date;
            }
            return null;
        } catch (InterruptedException e) {
            e.printStackTrace();
            return null;
        } finally {
            if (!ObjectUtils.isEmpty(lock)) {
                // 释放锁
                lock.unlock();
            }
        }
    }

    private void setBillAddReq(BillAddRequest billAddRequest, OrderInfo orderInfo, Date date) {
        billAddRequest.setOrderId(orderInfo.getId());
        billAddRequest.setTcWaybillNo(orderInfo.getTcWaybillNo());
        billAddRequest.setPricePaid(orderInfo.getPricePaid());
        billAddRequest.setUpdateTime(date);
        billAddRequest.setUserId(orderInfo.getUserId());
        billAddRequest.setType(OrderTypeEnum.REFUND.getValue());
        billRest.add(billAddRequest);
    }

    private void setOrderInfoAndTaskStatusLog(TaskStatusLog taskStatusLog, OrderInfo orderInfo, Date date, String processedBy) {
        orderInfo.setUpdateTime(date);
//        orderInfo.setType(OrderTypeEnum.REFUND.getValue());
        orderInfoMapper.updateById(orderInfo);
        taskStatusLog.setProcessedBy(processedBy);
        taskStatusLog.setTaskId(orderInfo.getId());
        taskStatusLog.setCreateTime(date);
        taskStatusLog.setUpdateTime(date);
        taskStatusLog.setUserId(orderInfo.getUserId());
        taskStatusLogRest.add(taskStatusLog);
    }

    public void restoreCreditLimit(BigDecimal pricePaid, String userId) {
        UserCompany userCompany = null;
        if (StringUtils.isNotBlank(userId)) {
            userCompany = userCompanyRest.getByUserId(userId);
        }
        if (!ObjectUtils.isEmpty(userCompany)) {
            BigDecimal usedCreditLimit = userCompany.getUsedCreditLimit();
            // 已用的减去取消的
            usedCreditLimit = usedCreditLimit.subtract(pricePaid);
            userCompany.setUsedCreditLimit(usedCreditLimit);
            userCompany.setUpdateTime(new Date());
            userCompanyMapper.updateById(userCompany);
        }
    }

    @ApiModelProperty(value = "恢复库存")
    @Override
    public void restoreInventory(String orderSn) {
        Lock lock = null;
        try {
            lock = redissonClient.getLock(ServicePrefixEnum.RESCUE + RedisPrefixKey.APPLET_INVENTORY_CHANGE + orderSn);
            //也可以指定锁时间的
            boolean b = lock.tryLock(lockTryTime, TimeUnit.SECONDS);
            if (b) {
                //业务
                Date date = new Date();
                List<OrderCommodity> orderCommodities = orderCommodityRest.getByOrderSn(orderSn);
                if (!CollectionUtils.isEmpty(orderCommodities)) {
                    List<String> commodityIds = orderCommodities.stream().map(orderCommodity -> orderCommodity.getCommodityId()).collect(Collectors.toList());
                    List<Commodity> commodities = commodityMapper.selectBatchIds(commodityIds);
                    orderCommodities.forEach(orderCommodity -> {
                        commodities.forEach(commodity -> {
                            if (orderCommodity.getCommodityId().equals(commodity.getId())) {
                                commodity.setAmount(commodity.getAmount() + orderCommodity.getCnt());
                                commodity.setUpdateTime(date);
                                commodityMapper.updateById(commodity);
                            }
                        });
                    });
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (!ObjectUtils.isEmpty(lock)) {
                // 释放锁
                lock.unlock();
            }
        }


    }

    @Override
    public RespJsonPageData<DistributionOrderListRes> queryOrderList(OrderInfoReq orderInfoReq) {
        List<String> userIds = new ArrayList<>(10);
        List<User> userList = new ArrayList<>(10);
        List<Integer> platformCodeList = new ArrayList<>(2);
        //月结的
        if (!PLATFORM_CODE.equals(orderInfoReq.getOrderInquiryEntry())) {
            userIds.add(JwtUtil.getUserId());
            platformCodeList.add(4);
        } else {
            //运控的
            if (ObjectUtils.isEmpty(orderInfoReq.getPlatformCode())) {
                platformCodeList.add(1);
                platformCodeList.add(4);
                platformCodeList.add(5);
            } else {
                platformCodeList.add(orderInfoReq.getPlatformCode());
            }
            if (StringUtils.isNotBlank(orderInfoReq.getPhoneNumber())) {
                userList = userMapper.selectList(new QueryWrapper<User>().eq("phone_number", phoneEncoderUtil.encryptString(orderInfoReq.getPhoneNumber())).in("platform_code", platformCodeList));
            }
            userIds = userList.stream().map(User::getId).collect(Collectors.toList());
        }
        LambdaQueryWrapper<OrderInfo> wrapper = Wrappers.lambdaQuery();
        wrapper.like(StringUtils.isNotBlank(orderInfoReq.getTcWayBillNo()), OrderInfo::getTcWaybillNo, orderInfoReq.getTcWayBillNo()).like(!ObjectUtils.isEmpty(orderInfoReq.getThirdPartyOrderNumber()), OrderInfo::getThirdPartyOrderNumber, orderInfoReq.getThirdPartyOrderNumber()).in(!CollectionUtils.isEmpty(userIds), OrderInfo::getUserId, userIds).eq(!ObjectUtils.isEmpty(orderInfoReq.getSenderTel()), OrderInfo::getSenderTel, phoneEncoderUtil.encryptString(orderInfoReq.getSenderTel())).eq(!ObjectUtils.isEmpty(orderInfoReq.getReceiverTel()), OrderInfo::getReceiverTel, phoneEncoderUtil.encryptString(orderInfoReq.getReceiverTel())).eq(!ObjectUtils.isEmpty(orderInfoReq.getOrderStatus()), OrderInfo::getOrderStatus, orderInfoReq.getOrderStatus()).le(StringUtils.isNotBlank(orderInfoReq.getOrderEndDate()), OrderInfo::getCreateTime, orderInfoReq.getOrderEndDate()).ge(StringUtils.isNotBlank(orderInfoReq.getOrderStartDate()), OrderInfo::getCreateTime, orderInfoReq.getOrderStartDate()).in(OrderInfo::getPlatformCode, platformCodeList).eq(ObjectUtil.isNotNull(orderInfoReq.getOrderType()), OrderInfo::getOrderType, orderInfoReq.getOrderType()).orderByDesc(OrderInfo::getCreateTime);
        Page<OrderInfo> orderInfoPageList = orderInfoMapper.selectPage(new Page<>(orderInfoReq.getPage(), orderInfoReq.getSize()), wrapper);
        //获取所有产品类型
        List<ProductTypeResp> productTypes = iProductTypeService.getProductType();
        if (CollectionUtils.isEmpty(orderInfoPageList.getRecords())) {
            return RespJsonPageData.success(new ArrayList<>(), 0);
        }
        Set<String> userIdSet = orderInfoPageList.getRecords().stream().map(OrderInfo::getUserId).collect(Collectors.toSet());
        Set<String> takeoffConnIdSet = orderInfoPageList.getRecords().stream().map(OrderInfo::getTakeoffConnId).collect(Collectors.toSet());
        Set<String> landingConnIdSet = orderInfoPageList.getRecords().stream().map(OrderInfo::getLandingConnId).collect(Collectors.toSet());
        takeoffConnIdSet.addAll(landingConnIdSet);
        List<TtTesTerminal> ttTesTerminalList = new ArrayList<>(10);
        Map<String, String> ttTesTerminalMap = new HashMap<>(10);
        if (!CollectionUtils.isEmpty(takeoffConnIdSet)) {
            ttTesTerminalList = ttTesTerminalMapper.selectList(new QueryWrapper<TtTesTerminal>().in("conn_id", takeoffConnIdSet));
        }
        if (!CollectionUtils.isEmpty(ttTesTerminalList)) {
            ttTesTerminalMap = ttTesTerminalList.stream().collect(Collectors.toMap(TtTesTerminal::getConnId, TtTesTerminal::getName, (value1, value2) -> value1));
        }
        List<User> users = userMapper.selectBatchIds(userIdSet);
        Map<String, String> userIdAndPhoneMap = users.stream().collect(Collectors.toMap(User::getId, User::getPhoneNumber, (value1, value2) -> value1));
        //userIdAndPhoneMap要先判空
        Map<String, String> allPhoneEncrypAndDecrypHashMap = batchDecryptionUtil.batchDecryption(orderInfoPageList.getRecords(), userIdAndPhoneMap);
        Set<String> goodsTypeIdSet = orderInfoPageList.getRecords().stream().map(OrderInfo::getGoodsTypeId).collect(Collectors.toSet());
        List<CityGoodsType> cityGoodsTypes = cityGoodsTypeMapper.selectBatchIds(goodsTypeIdSet);
        Map<String, String> cityGoodsIdAndTypeMap = cityGoodsTypes.stream().collect(Collectors.toMap(CityGoodsType::getId, CityGoodsType::getName, (value1, value2) -> value1));
        List<DistributionOrderListRes> distributionOrderListRes = BeanUtil.copyProperties(orderInfoPageList.getRecords(), DistributionOrderListRes.class);
        Map<String, String> finalTtTesTerminalMap = ttTesTerminalMap;
        distributionOrderListRes.forEach(distributionOrderRes -> {
            StringBuilder senderFullAddress = new StringBuilder();
            StringBuilder receiverFullAddress = new StringBuilder();
            senderFullAddress.append(distributionOrderRes.getSenderAddr());
            if (StringUtils.isNotBlank(distributionOrderRes.getSendAddressName())) {
                senderFullAddress.append(distributionOrderRes.getSendAddressName());
            }
            if (StringUtils.isNotBlank(distributionOrderRes.getSenderDoorplate())) {
                senderFullAddress.append(phoneEncoderUtil.decryptString(distributionOrderRes.getSenderDoorplate()));
            }
            distributionOrderRes.setSenderFullAddress(senderFullAddress.toString());

            receiverFullAddress.append(distributionOrderRes.getReceiverAddr());
            if (StringUtils.isNotBlank(distributionOrderRes.getReceiveAddressName())) {
                receiverFullAddress.append(distributionOrderRes.getReceiveAddressName());
            }
            if (StringUtils.isNotBlank(distributionOrderRes.getReceiverDoorplate())) {
                receiverFullAddress.append(phoneEncoderUtil.decryptString(distributionOrderRes.getReceiverDoorplate()));
            }
            distributionOrderRes.setReceiverFullAddress(receiverFullAddress.toString());
            distributionOrderRes.setGoodsTypeName(cityGoodsIdAndTypeMap.get(distributionOrderRes.getGoodsTypeId()));
            if (StringUtils.isNotBlank(userIdAndPhoneMap.get(distributionOrderRes.getUserId())) && !ObjectUtils.isEmpty(orderInfoReq.getExportOrNot()) && orderInfoReq.getExportOrNot()) {
                distributionOrderRes.setPhoneNumber(allPhoneEncrypAndDecrypHashMap.get(userIdAndPhoneMap.get(distributionOrderRes.getUserId())));
            } else {
                distributionOrderRes.setPhoneNumber(DesensitizedUtil.desensitized(allPhoneEncrypAndDecrypHashMap.get(userIdAndPhoneMap.get(distributionOrderRes.getUserId())), DesensitizedUtil.DesensitizedType.MOBILE_PHONE));
            }
            if (StringUtils.isNotBlank(distributionOrderRes.getSenderTel()) && !ObjectUtils.isEmpty(orderInfoReq.getExportOrNot()) && orderInfoReq.getExportOrNot()) {
                distributionOrderRes.setSenderTel(allPhoneEncrypAndDecrypHashMap.get(distributionOrderRes.getSenderTel()));
            } else {
                distributionOrderRes.setSenderTel(DesensitizedUtil.desensitized(allPhoneEncrypAndDecrypHashMap.get(distributionOrderRes.getSenderTel()), DesensitizedUtil.DesensitizedType.MOBILE_PHONE));
            }
            if (StringUtils.isNotBlank(distributionOrderRes.getReceiverTel()) && !ObjectUtils.isEmpty(orderInfoReq.getExportOrNot()) && orderInfoReq.getExportOrNot()) {
                distributionOrderRes.setReceiverTel(allPhoneEncrypAndDecrypHashMap.get(distributionOrderRes.getReceiverTel()));
            } else {
                distributionOrderRes.setReceiverTel(DesensitizedUtil.desensitized(allPhoneEncrypAndDecrypHashMap.get(distributionOrderRes.getReceiverTel()), DesensitizedUtil.DesensitizedType.MOBILE_PHONE));
            }
            if (!CollectionUtils.isEmpty(finalTtTesTerminalMap) && StringUtils.isNotBlank(distributionOrderRes.getLandingConnId())) {
                distributionOrderRes.setLandingName(finalTtTesTerminalMap.get(distributionOrderRes.getLandingConnId()));
            }
            if (!CollectionUtils.isEmpty(finalTtTesTerminalMap) && StringUtils.isNotBlank(distributionOrderRes.getTakeoffConnId())) {
                distributionOrderRes.setTakeoffName(finalTtTesTerminalMap.get(distributionOrderRes.getTakeoffConnId()));
            }
            if (!PLATFORM_CODE.equals(orderInfoReq.getOrderInquiryEntry())) {
                distributionOrderRes.setStatusName(MspOrderStatusEnum.getName(distributionOrderRes.getOrderStatus()));
            } else {
                distributionOrderRes.setStatusName(OrderStatusEnum.getName(distributionOrderRes.getOrderStatus()));
            }
            distributionOrderRes.setPlatformName(PlatformCodeEnum.getName(distributionOrderRes.getPlatformCode()));
            if (ObjectUtil.isNotNull(distributionOrderRes.getOrderType())) {
                List<ProductTypeResp> list = productTypes.stream().filter(item -> item.getProductType().equals(distributionOrderRes.getOrderType())).toList();
                if (CollUtil.isNotEmpty(list)) {
                    distributionOrderRes.setOrderTypeStr(list.get(0).getName());
                }
//                distributionOrderRes.setOrderTypeStr(ActivityProductTypeEnum.getName(distributionOrderRes.getOrderType()));
            }
        });
        return RespJsonPageData.success(distributionOrderListRes, orderInfoPageList.getTotal());
    }

    /**
     * 校验询单入参
     */
    public void checkMatchingSitesData(PreCarrierWaybillRequest preCarrierWaybillRequest) {
        String senderCity = preCarrierWaybillRequest.getSenderCity();
        String receiverCity = preCarrierWaybillRequest.getReceiverCity();
        double goodsWeight = preCarrierWaybillRequest.getGoodsWeight();
        if (goodsWeight <= 0) {
            throw new RuntimeException("货物重量不符合寄件要求");
        }
        if (senderCity.equals(receiverCity)) {
            //同城
            if (goodsWeight > sameCityMaxWeight) {
                throw new RuntimeException("货物重量不符合寄件要求");
            }
        } else {
            //跨城
            if (goodsWeight > crossCityMaxWeight) {
                throw new RuntimeException("货物重量不符合寄件要求");
            }
        }

    }

    @Override
    public CarrierWaybillResponse matchingSites(PreCarrierWaybillRequest preCarrierWaybillRequest) {
        String senderCity = preCarrierWaybillRequest.getSenderCity();
        String receiverCity = preCarrierWaybillRequest.getReceiverCity();
        Byte outerProductType = preCarrierWaybillRequest.getOuterProductType();
        Byte productType = ActivityProductTypeEnum.CROSS_REGION.getCode();
        if (senderCity.contains("undefined") || receiverCity.contains("undefined")) {
            //传入的城市有问题，通过经纬度反查，比较是否同城
            String senderLat = preCarrierWaybillRequest.getSenderLat();
            String senderLon = preCarrierWaybillRequest.getSenderLon();
            String receiverLat = preCarrierWaybillRequest.getReceiverLat();
            String receiverLon = preCarrierWaybillRequest.getReceiverLon();
            Map<String, Object> stringObjectMap = AddressUtils.getLocation(senderLon, senderLat);
            Map<String, Object> stringObjectMap1 = AddressUtils.getLocation(receiverLon, receiverLat);
            senderCity = stringObjectMap.get("province").toString() + stringObjectMap.get("city").toString();
            receiverCity = stringObjectMap1.get("province").toString() + stringObjectMap1.get("city").toString();
        }
        if (senderCity.equals(receiverCity)) {
            //同城
            productType = ActivityProductTypeEnum.LOCAL.getCode();
            if (!ObjectUtils.isEmpty(outerProductType) && outerProductType.equals(ActivityProductTypeEnum.CROSS_REGION.getCode())) {
                throw new RuntimeException("同城订单不能选中跨城");
            }
        } else {
            if (!ObjectUtils.isEmpty(outerProductType) && outerProductType.equals(ActivityProductTypeEnum.LOCAL.getCode())) {
                throw new RuntimeException("跨城订单不能选中同城");
            }
        }
        Boolean isCalculatePrice = preCarrierWaybillRequest.getIsCalculatePrice();
        this.checkMatchingSitesData(preCarrierWaybillRequest);
        Integer platformCode = preCarrierWaybillRequest.getPlatformCode();
        CarrierWaybillRequest carrierWaybillRequest = BeanUtil.copyProperties(preCarrierWaybillRequest, CarrierWaybillRequest.class);
        String senderLonUuid = preCarrierWaybillRequest.getSenderLonUuid();
        String receiverLonUuid = preCarrierWaybillRequest.getReceiverLonUuid();
        String senderLat = carrierWaybillRequest.getSenderLat();
        String senderLon = carrierWaybillRequest.getSenderLon();
        String receiverLat = carrierWaybillRequest.getReceiverLat();
        String receiverLon = carrierWaybillRequest.getReceiverLon();
        String expenseDetailsId = carrierWaybillRequest.getExpenseDetailsId();
        double goodsWeight = preCarrierWaybillRequest.getGoodsWeight();
        double transfer = goodsWeight * 1000;
        carrierWaybillRequest.setGoodsWeight((int) transfer);
        List<Long> senderAirportIds = (List<Long>) redisTemplate.opsForValue().get(ServicePrefixEnum.SAME_CITY + RedisPrefixKey.RECORD_AIR_PORT + senderLonUuid);
        redisTemplate.delete(ServicePrefixEnum.SAME_CITY + RedisPrefixKey.RECORD_AIR_PORT + senderLonUuid);
        List<Long> receiverAirportIds = (List<Long>) redisTemplate.opsForValue().get(ServicePrefixEnum.SAME_CITY + RedisPrefixKey.RECORD_AIR_PORT + receiverLonUuid);
        redisTemplate.delete(ServicePrefixEnum.SAME_CITY + RedisPrefixKey.RECORD_AIR_PORT + receiverLonUuid);
        if (CollectionUtils.isEmpty(senderAirportIds)) {
            senderAirportIds = airportInfoController.obtainTheNearestTerminalWithinTheRangeNow(Double.valueOf(senderLon), Double.valueOf(senderLat));
        }
        if (CollectionUtils.isEmpty(receiverAirportIds)) {
            receiverAirportIds = airportInfoController.obtainTheNearestTerminalWithinTheRangeNow(Double.valueOf(receiverLon), Double.valueOf(receiverLat));
        }
        logger.info("senderAirportIds:{}", senderAirportIds);
        logger.info("receiverAirportIds:{}", receiverAirportIds);
        carrierWaybillRequest.setSenderAirportIds(senderAirportIds);
        carrierWaybillRequest.setReceiverAirportIds(receiverAirportIds);
        //平台组没有物品类型概念，固定传1
        carrierWaybillRequest.setGoodsType(1);
        JSONObject jsonObject = intraCityRest.carrierWaybill(carrierWaybillRequest);

        if (jsonObject.getBoolean("success")) {
            if (!ObjectUtils.isEmpty(isCalculatePrice) && !isCalculatePrice) {
                return new CarrierWaybillResponse();
            }
            String takeoffConnId = jsonObject.getJSONObject("obj").getString("takeoffConnId");
            String landingConnId = jsonObject.getJSONObject("obj").getString("landingConnId");

            String takeoffCode = jsonObject.getJSONObject("obj").getString("takeoffCode");
            String landingCode = jsonObject.getJSONObject("obj").getString("landingCode");
            CarrierWaybillResponse carrierWaybillResponse = new CarrierWaybillResponse();
            carrierWaybillResponse.setTakeoffConnId(takeoffConnId);
            carrierWaybillResponse.setLandingConnId(landingConnId);
            carrierWaybillResponse.setSenderCity(preCarrierWaybillRequest.getSenderCity());
            carrierWaybillResponse.setReceiverCity(preCarrierWaybillRequest.getReceiverCity());
            //计算配送距离
            double jl = LocationUtils.getDistance(Double.valueOf(senderLat), Double.valueOf(senderLon), Double.valueOf(receiverLat), Double.valueOf(receiverLon));
            BigDecimal jlBigDecimal = new BigDecimal(jl / 1000).setScale(1, RoundingMode.HALF_UP);
            carrierWaybillResponse.setOrderDistance(jlBigDecimal);
            this.matchingSitesAfterDeal(jsonObject);
            //计价
            Calendar calendar = Calendar.getInstance();
            int hour = calendar.get(Calendar.HOUR_OF_DAY);
            int minute = calendar.get(Calendar.MINUTE);
            int second = calendar.get(Calendar.SECOND);
            List<Byte> productTypes = new ArrayList<>();
            productTypes.add(productType);
            productTypes.add(ActivityProductTypeEnum.SPECIAL_PLANE.getCode());
            List<Pricing> pricingList = pricingRest.getPriceByProductTypes(productTypes, hour * 3600 + minute * 60 + second);
            Date date = new Date();


            String userCouponId = carrierWaybillRequest.getUserCouponId();

            if (CollectionUtils.isEmpty(pricingList)) {
                throw new RuntimeException("当前地区暂未开通无人机服务，敬请期待");
//                expenseDetails.setBasePrice(expressFee);
//                carrierWaybillResponse.setBasePrice(expressFee);
//                expenseDetails.setOverweightCharges(new BigDecimal(0));
//                expenseDetails.setOverDistanceCharges(new BigDecimal(0));
//                finalPrice = expressFee;
//                estimatedPrice = expressFee;
            } else {
                List<PriceUnitResponse> priceUnitResponses = new ArrayList<>();
                for (int i = 0; i < pricingList.size(); i++) {
                    Pricing pricing = pricingList.get(i);
                    BigDecimal price = pricing.getPrice();
                    //查找是否有正向特殊定价
                    SpecialPricing specialPricing = specialPricingRest.getPrice(takeoffCode, landingCode, pricing.getId());
                    if (!ObjectUtils.isEmpty(specialPricing)) {
                        price = specialPricing.getPrice();
                    } else {
                        //查找是否有反向特殊定价
                        SpecialPricing bothWayPrice = specialPricingRest.getPrice(landingCode, takeoffCode, pricing.getId());
                        if (!ObjectUtils.isEmpty(bothWayPrice)) {
                            if (bothWayPrice.getIsItBidirectional().equals(BooleanEnum.TRUE.getValue())) {
                                price = bothWayPrice.getPrice();
                            }
                        }
                    }
                    //记录到数据库
                    ExpenseDetails expenseDetails = new ExpenseDetails();
                    if (!ObjectUtils.isEmpty(expenseDetailsId)) {
                        expenseDetails = expenseDetailsMapper.selectById(expenseDetailsId);
                    }
                    if (ObjectUtils.isEmpty(expenseDetails)) {
                        expenseDetails = new ExpenseDetails();
                    }
                    if ((ObjectUtils.isEmpty(outerProductType) && i == 0) || (!ObjectUtils.isEmpty(outerProductType) && pricing.getProductType().equals(outerProductType))) {
                        Byte pricingProductType = pricing.getProductType();
                        expenseDetails.setProductType(pricingProductType);
                        carrierWaybillResponse.setSelProductType(pricingProductType);
                        //如果没有选中产品类型就显示第一个
                        BigDecimal finalPrice;
                        //1、基础配送费，是给前端展示的，是没有计算超重超距之前的价格，前端还会显示超重超距费用，都加上就等于预估金额
                        carrierWaybillResponse.setBasePrice(price);
                        expenseDetails.setBasePrice(price);


                        //2、计算超范围之后的价格
                        JSONObject j = pricingRest.calculateMarkup(goodsWeight, jlBigDecimal, pricing.getId(), price);

                        carrierWaybillResponse.setOverweightCharges(((BigDecimal) j.get("overweightCharges")).setScale(2, RoundingMode.HALF_UP));
                        carrierWaybillResponse.setOverDistanceCharges(((BigDecimal) j.get("overDistanceCharges")).setScale(2, RoundingMode.HALF_UP));
                        finalPrice = (BigDecimal) j.get("price");


                        expenseDetails.setUpdateTime(date);
                        expenseDetails.setOrderDistance(carrierWaybillResponse.getOrderDistance());
                        expenseDetails.setOverDistanceCharges(carrierWaybillResponse.getOverDistanceCharges());
                        expenseDetails.setOverweightCharges(carrierWaybillResponse.getOverweightCharges());
                        //3、【这里就是步骤2获取到的计算超重超距之后的价格】应付金额等于算了超距超重之后但是没算优惠[小程序的优惠券优惠/企业折扣优惠]之前的价格，要处理历史数据
                        expenseDetails.setPricePayable(finalPrice);
                        carrierWaybillResponse.setPricePayable(finalPrice);


                        if (!ObjectUtils.isEmpty(userCouponId) && !ObjectUtils.isEmpty(expenseDetailsId)) {
                            //第一次询单肯定没有选择优惠券id,第二次才可能选择优惠券id,第二次询单expenseDetailsId不可能为空
                            //还需要计算优惠券
                            CouponPriceResponse couponPriceResponse = userCouponRest.calculatePrice(finalPrice, userCouponId);
                            BigDecimal reductionPrice = couponPriceResponse.getReductionPrice();
                            BigDecimal discount = couponPriceResponse.getDiscount();
                            Byte couponType = couponPriceResponse.getCouponType();
                            //4、计算优惠券之后的金额，使用了优惠券才有优惠金额这个概念
                            finalPrice = couponPriceResponse.getPrice();
                            carrierWaybillResponse.setReductionPrice(reductionPrice);
                            carrierWaybillResponse.setDiscount(discount);
                            carrierWaybillResponse.setCouponType(couponType);

                            //如果没有选择优惠券要清空优惠券信息
                            expenseDetails.setDiscount(discount);
                            expenseDetails.setCouponType(couponType);
                            expenseDetails.setReductionPrice(reductionPrice);
                        } else {
                            //如果没有选择优惠券要清空优惠券信息
                            expenseDetails.setDiscount(null);
                            expenseDetails.setCouponType(null);
                            expenseDetails.setReductionPrice(BigDecimal.ZERO);
                        }
                        if (PlatformCodeEnum.MONTHLY_SETTLEMENT_PLATFORM.getCode().equals(platformCode)) {
                            //月结平台需要计算企业折扣
                            //计算优惠价格
                            String userId = JwtUtil.getUserId();
                            UserCompany userCompany = userCompanyRest.getByUserId(userId);
                            if (!ObjectUtils.isEmpty(userCompany)) {
                                BigDecimal discount = userCompany.getDiscount();
                                if (!ObjectUtils.isEmpty(discount)) {
                                    carrierWaybillResponse.setDiscount(discount);
                                    BigDecimal reductionPrice = finalPrice.multiply(new BigDecimal(10).subtract(discount)).divide(new BigDecimal(10), 2, BigDecimal.ROUND_HALF_UP);
                                    carrierWaybillResponse.setReductionPrice(reductionPrice);
                                    expenseDetails.setReductionPrice(reductionPrice);
                                    finalPrice = finalPrice.multiply(discount).divide(new BigDecimal(10), 2, BigDecimal.ROUND_HALF_UP);
                                }
                            }
                        }
                        finalPrice = finalPrice.setScale(2, RoundingMode.HALF_UP);
                        //下面这两个价格，在下单时候用来对照是否完全一致的
                        carrierWaybillResponse.setPrice(finalPrice);
                        expenseDetails.setPrice(finalPrice);
                        if (!ObjectUtils.isEmpty(expenseDetailsId)) {
                            expenseDetailsMapper.updateById(expenseDetails);
                        } else {
                            expenseDetails.setCreateTime(date);
                            expenseDetailsMapper.insert(expenseDetails);
                        }
                        carrierWaybillResponse.setExpenseDetailsId(expenseDetails.getId());
                    }

                    PriceUnitResponse priceUnitResponse = new PriceUnitResponse();
                    priceUnitResponse.setEstimatedPrice(price);
                    priceUnitResponse.setDeliveryTime(pricing.getDeliveryTime());
                    priceUnitResponse.setProductType(pricing.getProductType());
                    priceUnitResponse.setProductTypeName(pricing.getProductTypeName());
                    priceUnitResponses.add(priceUnitResponse);
                }
                carrierWaybillResponse.setPriceUnitResponses(priceUnitResponses);
                return carrierWaybillResponse;
            }
        } else {
            // 调用失败,给出对应的异常
            String errorCode = jsonObject.getString("errorCode");
            String errorMessage = jsonObject.getString("errorMessage");
            if (errorCode.equals(PlatformGroupErrorEnum.PARAMETER_ERROR.getErrCode())) {
                errorMessage = PlatformGroupErrorEnum.PARAMETER_ERROR.getNewErrMsg();
            } else if (errorCode.equals(PlatformGroupErrorEnum.UNKNOWN_EXCEPTION.getErrCode())) {
                errorMessage = PlatformGroupErrorEnum.UNKNOWN_EXCEPTION.getNewErrMsg();
            } else if (errorCode.equals(PlatformGroupErrorEnum.THE_TYPE_OF_GOODS_UN_SUPPORT_UAV.getErrCode())) {
                errorMessage = PlatformGroupErrorEnum.THE_TYPE_OF_GOODS_UN_SUPPORT_UAV.getNewErrMsg();
            } else if (errorCode.equals(PlatformGroupErrorEnum.NOT_DURING_BUSINESS_HOURS.getErrCode())) {
                if (errorMessage.equals(PlatformGroupErrorEnum.NOT_DURING_BUSINESS_HOURS.getErrMsg())) {
                    errorMessage = PlatformGroupErrorEnum.NOT_DURING_BUSINESS_HOURS.getNewErrMsg();
                } else if (errorMessage.equals(PlatformGroupErrorEnum.NO_AVAILABLE_BUSINESS_TERMINALS.getErrMsg())) {
                    errorMessage = PlatformGroupErrorEnum.NO_AVAILABLE_BUSINESS_TERMINALS.getNewErrMsg();
                } else if (errorMessage.equals(PlatformGroupErrorEnum.THE_RECIPIENT_IS_NOT_WITHIN_THE_SERVICE_SCOPE.getErrMsg())) {
                    errorMessage = PlatformGroupErrorEnum.THE_RECIPIENT_IS_NOT_WITHIN_THE_SERVICE_SCOPE.getNewErrMsg();
                } else if (errorMessage.equals(PlatformGroupErrorEnum.THE_SENDER_IS_NOT_WITHIN_THE_SERVICE_SCOPE.getErrMsg())) {
                    errorMessage = PlatformGroupErrorEnum.THE_SENDER_IS_NOT_WITHIN_THE_SERVICE_SCOPE.getNewErrMsg();
                } else if (errorMessage.equals(PlatformGroupErrorEnum.NO_NAVIGABLE_ROUTE.getErrMsg())) {
                    errorMessage = PlatformGroupErrorEnum.NO_NAVIGABLE_ROUTE.getNewErrMsg();
                } else if (errorMessage.equals(PlatformGroupErrorEnum.OVERWEIGHT.getErrMsg())) {
                    errorMessage = PlatformGroupErrorEnum.OVERWEIGHT.getNewErrMsg();
                } else if (errorMessage.equals(PlatformGroupErrorEnum.CLOSE.getErrMsg())) {
                    errorMessage = PlatformGroupErrorEnum.CLOSE.getNewErrMsg();
                }
            } else if (errorCode.equals(PlatformGroupErrorEnum.THE_ORDER_ALREADY_EXISTS.getErrCode())) {
                errorMessage = PlatformGroupErrorEnum.THE_ORDER_ALREADY_EXISTS.getNewErrMsg();
            }
            logger.info(jsonObject.getString("errorMessage"));
            throw new RuntimeException(errorMessage);
        }
    }

    @Override
    public BigDecimal checkPrice(String expenseDetailsId, BigDecimal orderPrice) {
        ExpenseDetails expenseDetails = expenseDetailsMapper.selectById(expenseDetailsId);
        if (ObjectUtils.isEmpty(expenseDetails)) {
            throw new RuntimeException("费用明细不存在");
        }
        BigDecimal price = expenseDetails.getPrice();
        BigDecimal pricePayable = expenseDetails.getPricePayable();
        BigDecimal reductionPrice = expenseDetails.getReductionPrice();
        if (orderPrice.compareTo(price) != 0) {
            throw new RuntimeException("价格异常，请联系客服");
        }
        if (!ObjectUtils.isEmpty(reductionPrice)) {
            if (pricePayable.subtract(reductionPrice).compareTo(orderPrice) != 0) {
                throw new RuntimeException("价格异常，请联系客服");
            }
        }
        return expenseDetails.getPricePayable();
    }

    @Override
    public BigDecimal newCheckPrice(String expenseDetailsId, BigDecimal orderPrice, BigDecimal expenseDetailsPricePayable, BigDecimal reductionPrice) {
        ExpenseDetails expenseDetails = expenseDetailsMapper.selectById(expenseDetailsId);
        if (ObjectUtils.isEmpty(expenseDetails)) {
            throw new RuntimeException("费用明细不存在");
        }
        BigDecimal price = expenseDetails.getPrice();
        if (orderPrice.compareTo(price) != 0) {
            throw new RuntimeException("价格异常，请联系客服");
        }
        if (!ObjectUtils.isEmpty(reductionPrice)) {
            if (expenseDetailsPricePayable.subtract(reductionPrice).compareTo(orderPrice) != 0) {
                throw new RuntimeException("价格异常，请联系客服");
            }
        }
        return expenseDetails.getPricePayable();
    }

    @Async
    protected void matchingSitesAfterDeal(JSONObject jsonObject) {
        Date date = new Date();
        String takeoffConnId = jsonObject.getJSONObject("obj").getString("takeoffConnId");
        String takeoffLon = jsonObject.getJSONObject("obj").getString("takeoffLon");
        String takeoffLat = jsonObject.getJSONObject("obj").getString("takeoffLat");
        String takeoffName = jsonObject.getJSONObject("obj").getString("takeoffName");
        String takeoffAddr = jsonObject.getJSONObject("obj").getString("takeoffAddr");
        String landingConnId = jsonObject.getJSONObject("obj").getString("landingConnId");
        String landingLon = jsonObject.getJSONObject("obj").getString("landingLon");
        String landingLat = jsonObject.getJSONObject("obj").getString("landingLat");
        String landingName = jsonObject.getJSONObject("obj").getString("landingName");
        String landingAddr = jsonObject.getJSONObject("obj").getString("landingAddr");
        CityAirport cityAirport = cityAirportRest.selectByConnId(takeoffConnId);
        if (ObjectUtils.isEmpty(cityAirport)) {
            CityAirportAddRequest cityAirportAddRequest = new CityAirportAddRequest();
            cityAirportAddRequest.setAddr(takeoffAddr);
            cityAirportAddRequest.setConnId(takeoffConnId);
            cityAirportAddRequest.setName(takeoffName);
            cityAirportAddRequest.setLat(takeoffLat);
            cityAirportAddRequest.setLon(takeoffLon);
            cityAirportAddRequest.setCreateTime(date);
            cityAirportAddRequest.setUpdateTime(date);
            cityAirportRest.add(cityAirportAddRequest);
        }
        CityAirport endCityAirport = cityAirportRest.selectByConnId(landingConnId);
        if (ObjectUtils.isEmpty(endCityAirport)) {
            CityAirportAddRequest cityAirportAddRequest = new CityAirportAddRequest();
            cityAirportAddRequest.setAddr(landingAddr);
            cityAirportAddRequest.setConnId(landingConnId);
            cityAirportAddRequest.setName(landingName);
            cityAirportAddRequest.setLat(landingLat);
            cityAirportAddRequest.setLon(landingLon);
            cityAirportAddRequest.setCreateTime(date);
            cityAirportAddRequest.setUpdateTime(date);
            cityAirportRest.add(cityAirportAddRequest);
        }
    }


    @Override
    public Object confirmRefund(TradeRefundCallback tradeRefundCallback) {
        logger.info("tradeRefundCallback" + tradeRefundCallback.toString());
        QueryWrapper<OrderInfo> orderQueryWrapper = new QueryWrapper<>();
        orderQueryWrapper.eq("tc_waybill_no", tradeRefundCallback.getOutTradeNo());
        OrderInfo orderInfo = orderInfoMapper.selectOne(orderQueryWrapper);
        if (ObjectUtils.isEmpty(orderInfo)) {
            throw new RuntimeException("交易号不存在，请联系客服");
        }
        String refundStatus = tradeRefundCallback.getRefundStatus();
        //找到退款中的账单记录，更新为已退款/退款失败
        Bill bill = billRest.getByTcWaybillNo(orderInfo.getTcWaybillNo(), PayStatusEnum.REFUNDING.getValue());
        if ("success".equals(refundStatus)) {
            //退款成功
            orderInfoMapper.updateById(orderInfo);
            if (!ObjectUtils.isEmpty(bill)) {
                bill.setPayStatus(PayStatusEnum.REFUND.getValue());
            }
        } else {
            //退款失败
            orderInfoMapper.updateById(orderInfo);
            if (!ObjectUtils.isEmpty(bill)) {
                bill.setPayStatus(PayStatusEnum.REFUND_FAILED.getValue());
                bill.setRefundFailedReason(tradeRefundCallback.getErrMsg());
            }
        }
        if (!ObjectUtils.isEmpty(bill)) {
            bill.setUpdateTime(new Date());
            billMapper.updateById(bill);
        }
        return null;
    }

}
